Index: /tags/rel2_1/psLib/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/.cvsignore	(revision 1553)
@@ -0,0 +1,6 @@
+bin
+lib
+man
+psLib.kdevelop.*
+docs
+testbin
Index: /tags/rel2_1/psLib/src/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/src/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/src/.cvsignore	(revision 1553)
@@ -0,0 +1,1 @@
+DoxygenLog
Index: /tags/rel2_1/psLib/src/Doxyfile
===================================================================
--- /tags/rel2_1/psLib/src/Doxyfile	(revision 1553)
+++ /tags/rel2_1/psLib/src/Doxyfile	(revision 1553)
@@ -0,0 +1,1085 @@
+# Doxyfile 1.3.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "Pan-STARRS Foundation Library"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = 2.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../docs
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = DoxygenLog
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = pslib.h \
+                         mainpage.dox \
+                         sysUtils \
+                         image \
+                         dataManip \
+                         collections \
+                         astronomy
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS          = *.h *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = *_wrap.c
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output dir.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 10
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = times
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimised for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assigments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED             = DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similiar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
+
Index: /tags/rel2_1/psLib/src/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/Makefile	(revision 1553)
@@ -0,0 +1,215 @@
+###############################################################################
+##
+##  Makefile:  psLib
+##
+##  $Revision: 1.17 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-07-29 21:55:44 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+# Define variable prefix to the top level project - psLib
+# This is necessary for definition in Makefile.Globals
+
+ifndef prefix
+    export prefix=$(shell cd ..;pwd)
+endif
+
+# Include the make global definitions for the project
+
+include Makefile.Globals
+
+# Detect and save the CVS for this makefile
+
+NAME:= "$Name: not supported by cvs2svn $ "
+ifeq ($(NAME), "ame:  $ ")
+   VERSION:= ": Project Version: Unknown "
+else
+   VERSION:= ": Project Version: $(NAME) "
+endif
+
+# Define the target to build
+
+ALLTARGETS = sysUtils collections image dataManip astronomy
+
+TARGET_DYNAMIC = libpslib.$(DLL)
+TARGET_STATIC = libpslib.a
+
+# Define the installation targets
+
+INSTALLTARGETS = installSysUtils installCollections installImage installDataManip installAstronomy
+
+# Define the clean up targets
+
+CLEANTARGETS = cleanSysUtils cleanCollections cleanImage cleanDataManip cleanAstronomy
+
+CLEANDEPTARGETS = cleandepSysUtils cleandepCollections cleandepImage cleandepDataManip cleandepAstronomy
+
+# Define the distribution clean up targets
+
+DISTCLEANTARGETS = distcleanSysUtils distcleanCollections distcleanImage distcleanDataManip distcleanAstronomy
+
+# Define PHONY target "all" which will make all necessary items
+
+all:	$(ALLTARGETS)
+	$(BUILD_DYNAMIC1) $(TARGET_STATIC) $(BUILD_DYNAMIC2) $(TARGET_DYNAMIC)
+	@echo ""
+	@echo "    ---- All targets built successfully $(VERSION) ----"
+	@echo ""
+
+# Define PHONY target "sysUtils" which will make the system utilites
+# portion of the psLib
+
+sysUtils:
+	$(MAKE) --directory=sysUtils all
+
+image:
+	$(MAKE) --directory=image all
+
+collections:
+	$(MAKE) --directory=collections all
+
+dataManip:
+	$(MAKE) --directory=dataManip all
+
+astronomy:
+	$(MAKE) --directory=astronomy all
+
+## ADD ADDITIONAL PORTIONS OF PSLIB HERE
+
+# Define PHONY target "installSysUtils" which will install all the necessary
+# files for system utilities portion of psLib
+
+installSysUtils:
+	$(MAKE) --directory=sysUtils install
+
+installImage:
+	$(MAKE) --directory=image install
+
+installCollections:
+	$(MAKE) --directory=collections install
+
+installDataManip:
+	$(MAKE) --directory=dataManip install
+
+installAstronomy:
+	$(MAKE) --directory=astronomy install
+
+# Define PHONY target "cleanSysUtils" which will clean up the development
+# area for system utilites
+
+cleanSysUtils:
+	$(MAKE) --directory=sysUtils clean
+
+cleanImage:
+	$(MAKE) --directory=image clean
+
+cleanCollections:
+	$(MAKE) --directory=collections clean
+
+cleanDataManip:
+	$(MAKE) --directory=dataManip clean
+
+cleanAstronomy:
+	$(MAKE) --directory=astronomy clean
+
+#Define PHONY target "cleandep*" which will clean up the dependency files
+
+cleandepSysUtils:
+	$(MAKE) --directory=sysUtils cleandep
+
+cleandepImage:
+	$(MAKE) --directory=image cleandep
+
+cleandepCollections:
+	$(MAKE) --directory=collections cleandep
+
+cleandepDataManip:
+	$(MAKE) --directory=dataManip cleandep
+
+cleandepAstronomy:
+	$(MAKE) --directory=astronomy cleandep
+
+# Define PHONY target "distcleanSysUtils which will clean up the distribution
+# files related to system utilities
+
+distcleanSysUtils:
+	$(MAKE) --directory=sysUtils distclean
+        
+distcleanImage:
+	$(MAKE) --directory=image distclean
+        
+distcleanCollections:
+	$(MAKE) --directory=collections distclean
+
+distcleanDataManip:
+	$(MAKE) --directory=dataManip distclean
+
+distcleanAstronomy:
+	$(MAKE) --directory=astronomy distclean
+
+
+# Rule to make include directory if needed
+
+$(includedir):
+	mkdir -p $(includedir)
+
+# Rule to make bin directory if needed
+
+$(bindir):
+	mkdir -p $(bindir)
+
+# Rule to make lib directory if needed
+
+$(libexecdir):
+	mkdir -p $(libexecdir)
+
+# Rule to make man directory if needed
+       
+$(mandir): 
+	mkdir -p $(mandir)
+        
+$(mandir)/man3: $(mandir)
+	mkdir -p $(mandir)/man3
+
+# Rule to make the installation directories if needed
+
+installdirs: $(includedir) $(bindir) $(libexecdir) $(mandir)
+
+# Define PHONY target "install" to make the necessary directories for
+# the installation
+
+install: all installdirs $(INSTALLTARGETS)
+	install *.h $(includedir)
+	install $(TARGET_STATIC) $(libexecdir)
+	install $(TARGET_DYNAMIC) $(libexecdir)
+
+# Define PHONY target "clean" to clean up the development areas for
+# psLib
+
+clean: $(CLEANTARGETS)
+	$(RM) -f $(TARGET_STATIC)
+	$(RM) -f $(TARGET_DYNAMIC)
+
+cleandep: $(CLEANDEPTARGETS)
+
+# Define PHONY target "distclean" to clean up the distribution area for
+# psLib
+
+distclean: $(DISTCLEANTARGETS)
+	$(RM) -f $(libexecdir)/$(TARGET_STATIC)
+	$(RM) -f $(libexecdir)/$(TARGET_DYNAMIC)
+	$(RM) -f $(TARGET_DYNAMIC)
+	$(RM) -f $(TARGET_STATIC)
+
+# Define PHONY target "docs" to generate the Doxygen files for psLib
+        
+docs:
+	$(DOCS)
+
+tags:	
+	cd $(IPPROOT) ; etags `find . \( -name \*.[chy] -o -name \*.cpp \) -print`
+
+# List of PHONY targets with make file
+.PHONY:  sysUtils collections image dataManip astronomy
Index: /tags/rel2_1/psLib/src/Makefile.Globals
===================================================================
--- /tags/rel2_1/psLib/src/Makefile.Globals	(revision 1553)
+++ /tags/rel2_1/psLib/src/Makefile.Globals	(revision 1553)
@@ -0,0 +1,100 @@
+################################################################################
+##
+##  Makefile:  Globals
+##
+##  Assumptions:    Variable "prefix" already defined
+##
+##  $Revision: 1.18 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-13 23:47:10 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+# Determine the operating system and set variable for later conditional use
+
+ifndef OSTYPE
+    OSTYPE = $(shell uname -s)
+endif
+
+# Set environment variables for the project's directory structure
+
+ifndef mandir
+    export mandir = $(prefix)/man
+endif
+
+ifndef includedir
+    export includedir = $(prefix)/include
+endif
+
+ifndef testbindir
+    export testbindir = $(prefix)/testbin
+endif
+
+ifndef bindir
+    export bindir = $(prefix)/bin
+endif
+
+ifndef libexecdir
+    export libexecdir = $(prefix)/lib
+endif
+
+ifndef sladir
+	export sladir =  /usr/local/star
+endif	
+
+# Set initial value for CFLAGS which will include all OS common flags for GCC
+
+CFLAGS := -O0 -g2 -Wall -Werror -std=c99 -D_GNU_SOURCE -pipe
+
+ifdef NO_TRACE
+CFLAGS := $(CFLAGS) -DPS_NO_TRACE=1
+endif
+ 
+# Set initial value for LDFLAGS which will include all OS common flags for GCC and required libraries.
+
+SLA_LINK := $(shell $(sladir)/bin/sla_link)
+EXTLIBS := -lcfitsio -lgsl -lgslcblas -lfftw3f -L$(sladir)/lib $(SLA_LINK) 
+LDFLAGS := -g2 -pipe $(EXTLIBS) 
+
+# Define or refine variables for the Linux OS
+
+ifneq "$(findstring inux,$(OSTYPE))" ""
+    CFLAGS_RELOC := $(CFLAGS) -fpic
+    LDFLAGS_SO := $(LDFLAGS) -fpic -shared -ldl
+    LDFLAGS_DLL := $(LDFLAGS) -fpic -shared
+    DLL = so
+    SO  = so
+    DOCS = doxygen Doxyfile
+    BUILD_DYNAMIC1 = $(CC) $(LDFLAGS_DLL) -Wl,--whole-archive
+    BUILD_DYNAMIC2 = -Wl,--no-whole-archive -lm -o
+endif
+
+ifneq "$(findstring arwin,$(OSTYPE))" ""
+    CFLAGS += -Wno-long-double -DDARWIN 
+    CFLAGS_RELOC := $(CFLAGS)
+    LDFLAGS := $(LDFLAGS) -lmx
+    LDFLAGS_SO := $(LDFLAGS) -bundle -flat_namespace -undefined suppress
+    LDFLAGS_DLL := $(LDFLAGS) -dynamiclib
+    DLL = dylib
+    SO = bundle
+    DOCS =
+    BUILD_DYNAMIC1 = libtool -dynamic
+    BUILD_DYNAMIC2 = -L/usr/local/star/lib -lm -lmx -lgcc $(EXTLIBS) -lg2c -o
+endif
+
+# Set default for variable CC
+
+ifndef CC
+    export CC=cc
+endif
+
+# Set default for variable LD
+
+ifndef LD
+    export LD=ld
+endif
+
+# Set list of PHONY targets
+.PHONY: all install distclean clean docs tags print_header
+
Index: /tags/rel2_1/psLib/src/astro/psCoord.c
===================================================================
--- /tags/rel2_1/psLib/src/astro/psCoord.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astro/psCoord.c	(revision 1553)
@@ -0,0 +1,453 @@
+/** @file  psCoord.c
+*
+*  @brief Contains basic coordinate transformation definitions and operations
+*
+*  This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup CoordinateTransform
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-13 23:43:29 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psCoord.h"
+#include "psMemory.h"
+#include "psAbort.h"
+#include "psTime.h"
+#include <math.h>
+#include <float.h>
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static float p_psCot(float x);
+static float p_psArg(float x, float y);
+
+/******************************************************************************
+XXX: Do this with a macro.
+ *****************************************************************************/
+float p_psCot(float x)
+{
+    return (1.0 / atan(x));
+}
+
+/******************************************************************************
+XXX: Verify this arc tan function.
+ *****************************************************************************/
+float p_psArg(float x,
+              float y)
+{
+    if (x > 0) {
+        return (atan(y / x));
+    } else if ((x == 0) && (y == 0)) {
+        return (0.5 * M_PI);
+    } else if ((x == 0) && (y == 0)) {
+        return (-0.5 * M_PI);
+    } else if ((x == 0) && (y == 0)) {
+        return (M_PI + atan(y / x));
+    } else if ((x == 0) && (y == 0)) {
+        return (-M_PI + atan(y / x));
+    }
+
+    psAbort(__func__, "Unacceptable range for (p_psArg(%f, %f).\n", x, y);
+    return (0.0);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+psPlane* psPlaneTransformApply(psPlane* out,
+                               const psPlaneTransform* transform,
+                               const psPlane* coords)
+{
+    if (out == NULL) {
+        out = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+    out->x = transform->x->coeff[0][0] +
+             (transform->x->coeff[1][0] * coords->x) +
+             (transform->x->coeff[0][1] * coords->y);
+
+    out->y = transform->y->coeff[0][0] +
+             (transform->y->coeff[1][0] * coords->x) +
+             (transform->y->coeff[0][1] * coords->y);
+
+    return (out);
+}
+
+/******************************************************************************
+This transformation takes into account parameters beyond an objects spatial
+coordinates: term3 and term4 (magnitude and color).
+ *****************************************************************************/
+psPlane* psPlaneDistortApply(psPlane* out,
+                             const psPlaneDistort* transform,
+                             const psPlane* coords,
+                             float color,
+                             float magnitude)
+{
+    if (out == NULL) {
+        out = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+
+    out->x = transform->x->coeff[0][0][0][0] +
+             (transform->x->coeff[1][0][0][0] * coords->x) +
+             (transform->x->coeff[0][1][0][0] * coords->y) +
+             (transform->x->coeff[0][0][1][0] * color) +
+             (transform->x->coeff[0][0][0][1] * magnitude);
+
+    out->y = transform->y->coeff[0][0][0][0] +
+             (transform->y->coeff[1][0][0][0] * coords->x) +
+             (transform->y->coeff[0][1][0][0] * coords->y) +
+             (transform->y->coeff[0][0][1][0] * color) +
+             (transform->y->coeff[0][0][0][1] * magnitude);
+
+    return (out);
+}
+
+/******************************************************************************
+This function prototype has been modified since the SDRS.
+ *****************************************************************************/
+psSphereTransform* psSphereTransformAlloc(double NPlat,
+        double Xo,
+        double xo)
+{
+    psSphereTransform* tmp = (psSphereTransform* ) psAlloc(sizeof(psSphereTransform));
+
+    tmp->sinPhi = sin(NPlat);
+    tmp->cosPhi = cos(NPlat);
+    tmp->Xo = Xo;
+    tmp->xo = xo;
+
+    return (tmp);
+}
+
+/******************************************************************************
+This algorithm comes from an email from Gene.  I assume (x,y) corresponds to
+(r,d) in the sphere coordinates.
+ 
+XXX: In Gene's email, there are different variables with similar names (y
+and Y) and in the code, there's cos_y, cos_Y, and cos(y).  Verify that there
+are no typo's.
+ *****************************************************************************/
+psSphere* psSphereTransformApply(psSphere* out,
+                                 const psSphereTransform* transform,
+                                 const psSphere* coord)
+{
+    double sinY = 0.0;
+    double cosY = 0.0;
+    double sinX = 0.0;
+    double cosX = 0.0;
+    double x = 0.0;
+    double y = 0.0;
+    double dx = 0.0;
+
+    if (out == NULL) {
+        out = (psSphere* ) psAlloc(sizeof(psSphere));
+    }
+
+    x = coord->r;
+    y = coord->d;
+    dx = x - transform->xo;
+    sinY = cos(y) * sin(dx) * transform->sinPhi + sin(y) * transform->cosPhi;
+    cosY = sqrt(1.0 - sinY * sinY);
+    sinX = (cos(y) * sin(dx) * transform->cosPhi - sin(y) * transform->sinPhi) / cos(y);
+    cosX = cos(y) * cos(dx) / cos(y);
+
+    out->r = atan2(sinX, cosX) + transform->Xo;
+    out->d = atan2(sinY, cosY);
+
+    return (out);
+}
+
+psSphereTransform* psSphereTransformICRStoEcliptic(psTime time)
+{
+    struct tm *tmTime = psTimeToTM(time);
+    double year = (double)(1900 + tmTime->tm_year);
+    double T = year / 100.0;
+    double phi = -23.452294 + 0.013013 * T + 0.000001639 * T * T - 0.000000503 * T * T * T;
+    double Xo = 0.0;
+    double xo = 0.0;
+
+    return (psSphereTransformAlloc(phi, Xo, xo));
+}
+
+psSphereTransform* psSphereTransformEcliptictoICRS(psTime time)
+{
+    struct tm *tmTime = psTimeToTM(time);
+    double year = (double)(1900 + tmTime->tm_year);
+    double T = year / 100.0;
+    double phi = +23.452294 - 0.013013 * T - 0.000001639 * T * T + 0.000000503 * T * T * T;
+    double Xo = 0.0;
+    double xo = 0.0;
+
+    return (psSphereTransformAlloc(phi, Xo, xo));
+}
+
+psSphereTransform* psSphereTransformICRStoGalatic(void)
+{
+    return (psSphereTransformAlloc(62.6, 282.25, 33.0));
+}
+
+psSphereTransform* psSphereTransformGalatictoICRS(void)
+{
+    return (psSphereTransformAlloc(-62.6, 33.0, 282.25));
+}
+
+/******************************************************************************
+XXX: Waiting for the definition of the PS_PROJ_PAR projection.
+XXX: Waiting for the definition of the PS_PROJ_GLS projection.
+ *****************************************************************************/
+psPlane* psProject(const psSphere* coord,
+                   const psProjection* projection)
+{
+    float R = 0.0;
+    float alpha = 0.0;
+    psPlane* tmp = (psPlane* ) psAlloc(sizeof(psPlane));
+
+    if (projection->type == PS_PROJ_TAN) {
+        R = p_psCot(coord->r) * (180.0 / M_PI);
+        tmp->x = R * sin(coord->d);
+        tmp->y = R * cos(coord->d);
+
+    } else if (projection->type == PS_PROJ_SIN) {
+        R = cos(coord->r) * (180.0 / M_PI);
+        tmp->x = R * sin(coord->d);
+        tmp->y = R * cos(coord->d);
+
+    } else if (projection->type == PS_PROJ_CAR) {
+        tmp->x = coord->d;
+        tmp->y = coord->r;
+
+    } else if (projection->type == PS_PROJ_MER) {
+        tmp->x = coord->d;
+        tmp->y = log(tan(45.0 + (0.5 * coord->r))) * 180.0 / M_PI;
+
+    } else if (projection->type == PS_PROJ_AIT) {
+        alpha = 1.0 / ((180.0 / M_PI) * sqrt(1.0 + (cos(coord->r) * cos(0.5 * coord->d) * 0.5)));
+
+        tmp->x = 2.0 * alpha * cos(coord->r) * sin(0.5 * coord->d);
+        tmp->y = alpha * sin(coord->d);
+
+    } else if (projection->type == PS_PROJ_PAR) {
+        psAbort(__func__, "The projection type PS_PROJ_PAR is undefined.\n");
+
+    } else if (projection->type == PS_PROJ_GLS) {
+        psAbort(__func__, "The projection type PS_PROJ_GLS is undefined.\n");
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+XXX: Waiting for the definition of the PS_PROJ_PAR projection.
+XXX: Waiting for the definition of the PS_PROJ_GLS projection.
+ *****************************************************************************/
+psSphere* psDeproject(const psPlane* coord,
+                      const psProjection* projection)
+{
+    float R = 0.0;
+    float chu = 0.0;
+    float chu1 = 0.0;
+    float chu2 = 0.0;
+    psSphere* tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+
+    if (projection->type == PS_PROJ_TAN) {
+        R = sqrt((coord->x * coord->x) + (coord->y * coord->y));
+        tmp->d = p_psArg(-coord->y, coord->x);
+        tmp->r = atan(180.0 / (R * M_PI));
+
+    } else if (projection->type == PS_PROJ_SIN) {
+        R = sqrt((coord->x * coord->x) + (coord->y * coord->y));
+        tmp->d = p_psArg(-coord->y, coord->x);
+        tmp->r = acos((R * M_PI) / 180.0);
+
+    } else if (projection->type == PS_PROJ_CAR) {
+        tmp->d = coord->x;
+        tmp->r = coord->y;
+
+    } else if (projection->type == PS_PROJ_MER) {
+        tmp->d = coord->x;
+        tmp->r = (2.0 * atan(exp((coord->y * M_PI / 180.0)))) - 180.0;
+
+    } else if (projection->type == PS_PROJ_AIT) {
+        chu1 = (coord->x * M_PI) / 720.0;
+        chu1 *= chu1;
+        chu2 = (coord->y * M_PI) / 360.0;
+        chu2 *= chu2;
+        chu = sqrt(1.0 - chu1 - chu2);
+        tmp->d = 2.0 * p_psArg((2.0 * chu * chu) - 1.0, (coord->x * chu * M_PI) / 360.0);
+        tmp->r = asin((coord->y * chu * M_PI) / 180.0);
+
+    } else if (projection->type == PS_PROJ_PAR) {
+        psAbort(__func__, "The projection type PS_PROJ_PAR is undefined.\n");
+
+    } else if (projection->type == PS_PROJ_GLS) {
+        psAbort(__func__, "The projection type PS_PROJ_GLG is undefined.\n");
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+The basic idea is to project both positions onto the linear plane, with
+position1 at the center, then calculate the linear offset between those
+projections.
+ 
+XXX: Do I need to check for unacceptable transformation parameters?  Maybe,
+     if the points are on the North/South Pole, etc?
+ 
+XXX: Do I need to somehow scale this projection?
+ *****************************************************************************/
+psSphere* psSphereGetOffset(const psSphere* restrict position1,
+                            const psSphere* restrict position2,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    psPlane* lin;
+    psProjection proj;
+    psSphere* tmp;
+    double tmpR = 0.0;
+    double tmpD = 0.0;
+
+    if (mode == PS_LINEAR) {
+        proj.R = position1->r;
+        proj.D = position1->d;
+        proj.Xs = 1.0;
+        proj.Ys = 1.0;
+        proj.type = PS_PROJ_TAN;
+
+        lin = psProject(position2, &proj);
+        tmp = psDeproject(lin, &proj);
+        psFree(lin);
+
+        // XXX: Do we need to convert units in tmp?
+        return (tmp);
+    } else if (mode == PS_SPHERICAL) {
+        tmpR = position2->r - position1->r;
+        tmpD = position2->d - position1->d;
+
+        if (unit == PS_ARCSEC) {
+            tmpR = (tmpR * 180.0 * 60.0 * 60.0) / M_PI;
+            tmpD = (tmpR * 180.0 * 60.0 * 60.0) / M_PI;
+        } else if (unit == PS_ARCMIN) {
+            tmpR = (tmpR * 180.0 * 60.0) / M_PI;
+            tmpD = (tmpR * 180.0 * 60.0) / M_PI;
+        } else if (unit == PS_DEGREE) {
+            tmpR = (tmpR * 180.0) / M_PI;
+            tmpD = (tmpR * 180.0) / M_PI;
+        } else if (unit == PS_RADIAN) {}
+        else {
+            psAbort(__func__, "Unknown offset unit: 0x%x\n", unit);
+        }
+
+        tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+        // XXX: Wrap these to an acceptable range.  Is this correct?
+        tmp->r = fmod(tmpR, 2*M_PI);
+        tmp->d = fmod(tmpD, 2*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        return (tmp);
+    }
+    psAbort(__func__, "Unrecognized offset mode\n");
+    return (NULL);
+}
+
+/******************************************************************************
+XXX: Do we need to check for unacceptable transformation parameters?  Maybe,
+     if the points are on the North/South Pole, etc?
+ 
+XXX: Do we need to somehow scale this projection?
+ 
+XXX: I copied the algorithm from the ADD exactly.
+ *****************************************************************************/
+
+psSphere* psSphereSetOffset(const psSphere* restrict position,
+                            const psSphere* restrict offset,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    psPlane lin;
+    psSphere* tmp;
+    psProjection proj;
+    double tmpR = 0.0;
+    double tmpD = 0.0;
+
+    if (mode == PS_LINEAR) {
+        proj.R = position->r;
+        proj.D = position->d;
+        proj.Xs = 1.0;
+        proj.Ys = 1.0;
+        proj.type = PS_PROJ_TAN;
+
+        lin.x = offset->r;
+        lin.y = offset->d;
+
+        tmp = psDeproject(&lin, &proj);
+        return (tmp);
+
+    } else if (mode == PS_SPHERICAL) {
+        if (unit == PS_ARCSEC) {
+            tmpR = (M_PI * offset->r) / (180.0 * 60.0 * 60.0);
+            tmpD = (M_PI * offset->d) / (180.0 * 60.0 * 60.0);
+        } else if (unit == PS_ARCMIN) {
+            tmpR = (M_PI * offset->r) / (180.0 * 60.0);
+            tmpD = (M_PI * offset->d) / (180.0 * 60.0);
+        } else if (unit == PS_DEGREE) {
+            tmpR = (M_PI * offset->r) / (180.0);
+            tmpD = (M_PI * offset->d) / (180.0);
+        } else if (unit == PS_RADIAN) {
+            tmpR = offset->r;
+            tmpD = offset->d;
+        } else {
+            psAbort(__func__, "Unknown offset unit: 0x%x\n", unit);
+        }
+
+        tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+        // XXX: Is this an acceptable way to wrap the angular output?
+        tmp->r = position->r + tmpR;
+        tmp->r = fmod(tmp->r, 2.0*M_PI);
+        tmp->d = position->d + tmpD;
+        tmp->d = fmod(tmp->d, 2.0*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        return (tmp);
+    }
+    psAbort(__func__, "Unrecognized offset mode\n");
+    return (NULL);
+}
Index: /tags/rel2_1/psLib/src/astro/psCoord.h
===================================================================
--- /tags/rel2_1/psLib/src/astro/psCoord.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astro/psCoord.h	(revision 1553)
@@ -0,0 +1,298 @@
+
+/** @file  psCoord.h
+*
+*  @brief Contains basic coordinate transformation definitions and operations
+*
+*  This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup CoordinateTransform
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 01:23:20 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_COORD_H
+#define PS_COORD_H
+
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psFunctions.h"
+#include "psTime.h"
+
+/// @addtogroup CoordinateTransform
+/// @{
+
+/** Euclidiean Coordinate System.
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One
+ *  coordinate system to be used is linear coordinates which conform to 
+ *  Euclidean geometry. 
+ *
+ */
+typedef struct
+{
+    double x;                   ///< x position
+    double y;                   ///< y position
+    double xErr;                ///< Error in x position
+    double yErr;                ///< Error in y position
+}
+psPlane;
+
+/** Angular Coordinate System
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One 
+ *  coordinate system to be used is angular coordinates for which additional 
+ *  care must often be taken in comparison to a euclidiean coordinate system.
+ *
+ */
+typedef struct
+{
+    double r;                   ///< RA
+    double d;                   ///< Dec
+    double rErr;                ///< Error in RA
+    double dErr;                ///< Error in Dec
+}
+psSphere;
+
+/** 2D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists simply of two 2D 
+ *  polynomials to transform both components - the output coordinates depend 
+ *  only on the input coordinates and no other quantities of objects at those
+ *  coordinates. 
+ *
+ */
+typedef struct
+{
+    psDPolynomial2D* x;         ///< 2D polynomial transform of X coordinates
+    psDPolynomial2D* y;         ///< 2D polynomial transform of Y coordinates
+}
+psPlaneTransform;
+
+/** 4D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists of two 4D polynomials
+ *  in which the output coordinates are also specified to be a function of the 
+ *  magnitude and color of the object with the given coordinates. This type of 
+ *  coordinate transformation is necessary to represent the (color-dependent) 
+ *  optical distortions caused by the atmosphere and camera optics, and the 
+ *  possibly effects of charge transfer inefficiency.
+ *
+ *  The lowest two terms are the x and y axis of the target system.  The higher
+ *  two terms may represent magnitude and color terms.
+ */
+typedef struct
+{
+    psDPolynomial4D* x;         ///< 4D polynomial transform of X coordinates
+    psDPolynomial4D* y;         ///< 4D polynomial transform of Y coordinates
+}
+psPlaneDistort;
+
+/** Spherical Transform Definition
+ *
+ *  We need to be able to convert between ICRS, Galactic and Ecliptic 
+ *  coordinates, and potentially between arbitrary spherical coordinate 
+ *  systems. All of these basic spherical transformations represent rotations 
+ *  of the spherical coordinate reference. We specify a general 
+ *  transformation function which takes a structure, psSphereTransform, 
+ *  defining the transformation between two spherical coordinate systems 
+ *
+ */
+typedef struct
+{
+    double sinPhi;              ///< sin of North Pole lattitude
+    double cosPhi;              ///< cos of North Pole lattitude
+    double Xo;                  ///< First PT of Ares lon
+    double xo;                  ///< First PT of Ares equiv lon
+}
+psSphereTransform;
+
+/** Projection type for projection/deprojection
+ * 
+ *  @see psProject, psDeproject
+ *
+ */
+typedef enum {
+    PS_PROJ_TAN,                ///< Tangent projection
+    PS_PROJ_SIN,                ///< Sine projection
+    PS_PROJ_AIT,                ///< Aitoff projection
+    PS_PROJ_PAR,                ///< Par projection
+    PS_PROJ_GLS,                ///< GLS projection
+    PS_PROJ_CAR,                ///< CAR projection
+    PS_PROJ_MER,                ///< MER projection
+    PS_PROJ_NTYPE               ///< Number of types; must be last.
+} psProjectionType;
+
+/** Parameter set for projection/deprojection
+ * 
+ *  @see psProject, psDeproject
+ *
+ */
+typedef struct
+{
+    double R;                   ///< Coordinates of projection center
+    double D;                   ///< Coordinates of projection center
+    double Xs;                  ///< plate-scale in X direction
+    double Ys;                  ///< plate-scale in Y direction
+    psProjectionType type;      ///< Projection type
+}
+psProjection;
+
+/** Mode for Offset calculation between two sky positions
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_SPHERICAL,               ///< offset corresponds to an angular offset
+    PS_LINEAR                   ///< offset corresponds to a linear offset
+} psSphereOffsetMode;
+
+/** The units of the offset
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_ARCSEC,                  ///< Arcseconds
+    PS_ARCMIN,                  ///< Arcminutes
+    PS_DEGREE,                  ///< Degrees
+    PS_RADIAN                   ///< Radians
+} psSphereOffsetUnit;
+
+/** Applies the psPlaneTransform transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneTransformApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneTransform* transform, ///< the transform to apply
+    const psPlane* coords              ///< the coordinate to apply the transform above.
+);
+
+/** Applies the psPlaneDistort transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneDistortApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneDistort* transform,   ///< the transform to apply
+    const psPlane* coords,             ///< the coordinate to apply the transform above.
+    float term3,                       ///< third term -- maybe magnitude
+    float term4                        ///< forth term -- maybe color
+);
+
+/** Allocator for psSphereTransform
+ *
+ *  @return psSphereTransform*         newly allocated struct
+ */
+psSphereTransform* psSphereTransformAlloc(
+    double NPlat,                      ///< north pole latitude
+    double Xo,                         ///< First PT of Ares lon
+    double xo                          ///< First PT of Ares equiv lon
+);
+
+/** Applies the psSphereTransform transform for a specified coordinate
+ *
+ *  @return psSphere*      resulting coordinate based on transform
+ */
+psSphere* psSphereTransformApply(
+    psSphere* out,                     ///< a psSphere to recycle.  If NULL, a new one is generated.
+    const psSphereTransform* transform,///< the transform to apply
+    const psSphere* coord              ///< the coordinate to apply the transform above.x
+);
+
+/** Creates the appropriate transform for converting from ICRS to Ecliptic
+ *  coordinate systems.
+ *
+ *  @return psSphereTransform*     transform for ICRS->Ecliptic coordinate systems
+ */
+psSphereTransform* psSphereTransformICRStoEcliptic(
+    psTime time                        ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from Ecliptic to ICRS
+ *  coordinate systems.
+ *
+ *  @return psSphereTransform*     transform for Ecliptic->ICRS coordinate systems
+ */
+psSphereTransform* psSphereTransformEcliptictoICRS(
+    psTime time                        ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from ICRS to Galatic
+ *  coordinate systems.
+ *
+ */
+psSphereTransform* psSphereTransformICRStoGalatic(void);
+
+/** Creates the appropriate transform for converting from Galatic to ICRS
+ *  coordinate systems.
+ *
+ */
+psSphereTransform* psSphereTransformGalatictoICRS(void);
+
+/** Projects a spherical coordinate to a linear coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psPlane* psProject(
+    const psSphere* coord,             ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Reverse projection of a linear coordinate to a spherical coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psSphere* psDeproject(
+    const psPlane* coord,              ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Determines the offset (RA,Dec) on the sky between two positions.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be 
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an 
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset 
+ *  corresponds to a linear offset in a local projection. The offset unit may 
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which 
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*    the offset between position1 and position2
+ */
+psSphere* psSphereGetOffset(
+    const psSphere* restrict position1,
+    const psSphere* restrict position2,
+    psSphereOffsetMode mode,
+    psSphereOffsetUnit unit
+);
+
+/** Applies the given offset to a coordinate.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be 
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an 
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset 
+ *  corresponds to a linear offset in a local projection. The offset unit may 
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which 
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*    the given position with the given offset applied.
+ */
+psSphere* psSphereSetOffset(
+    const psSphere* restrict position,
+    const psSphere* restrict offset,
+    psSphereOffsetMode mode,
+    psSphereOffsetUnit unit
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astro/psTime.c
===================================================================
--- /tags/rel2_1/psLib/src/astro/psTime.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astro/psTime.c	(revision 1553)
@@ -0,0 +1,549 @@
+
+/** @file  psTime.c
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy
+ *  functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
+ *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
+ *  base upon which International Atomic Time (TAI) time is calculated. TAI time varies over time due to the
+ *  earth's rotation and the movement of the continental plates. It is currentls 32 seconds faster than
+ *  UTC/timeval time.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-13 23:47:10 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psTime.h"
+#include "psError.h"
+#include "psMemory.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+/** Number of available leapsecond updates */
+#define NUM_LEAPSECOND_UPDATES 23
+
+/** Maximum length of time string */
+#define MAX_TIME_STRING_LENGTH 256
+
+/** Seconds per minute */
+#define  SEC_PER_MINUTE 60.0
+
+/** Seconds per hour */
+#define  SEC_PER_HOUR (60.0*SEC_PER_MINUTE)
+
+/** Seconds per day */
+#define  SEC_PER_DAY (24.0*SEC_PER_HOUR)
+
+/** Seconds per year */
+#define  SEC_PER_YEAR (365.0*SEC_PER_DAY)
+
+/** Microseconds per day */
+#define USEC_PER_DAY 86400000000.0
+
+/** Preprocessor macro to generate error for negative time in struct */
+#define CHECK_NEGATIVE_TIME_STRUCT(NAME,RETURN)                                                              \
+if(NAME.tv_sec < 0) {                                                                                        \
+    psError(__func__,"Negative seconds are not allowed: %ld", NAME.tv_sec);                                  \
+    return RETURN;                                                                                           \
+} else if(NAME.tv_usec<0) {                                                                                  \
+    psError(__func__,"Negative microseconds are not allowed: %ld", NAME.tv_usec);                            \
+    return RETURN;                                                                                           \
+}
+
+/** Preprocessor macro to generate error for negative time */
+#define CHECK_NEGATIVE_TIME(NAME,RETURN)                                                                     \
+if(NAME < 0.0) {                                                                                             \
+    psError(__func__,"Negative time is not allowed: %f", NAME);                                              \
+    return RETURN;                                                                                           \
+}                                                                                                            \
+
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+/* The table below comes from http://tycho.usno.navy.mil/leapsec.html, which reports the current state of
+the TAI/UTC leapsecond conversion times. This table is placed into a two dimensional array and used by
+the psTimeGetTime() function to calculate TAI time from  UTC time.
+ 
+ 1972 JAN 1 = JD 2441317.5  TAI-UTC = 10.0
+ 1972 JUL 1 = JD 2441499.5  TAI-UTC = 11.0
+ 1973 JAN 1 = JD 2441683.5  TAI-UTC = 12.0
+ 1974 JAN 1 = JD 2442048.5  TAI-UTC = 13.0
+ 1975 JAN 1 = JD 2442413.5  TAI-UTC = 14.0
+ 1976 JAN 1 = JD 2442778.5  TAI-UTC = 15.0
+ 1977 JAN 1 = JD 2443144.5  TAI-UTC = 16.0
+ 1978 JAN 1 = JD 2443509.5  TAI-UTC = 17.0
+ 1979 JAN 1 = JD 2443874.5  TAI-UTC = 18.0
+ 1980 JAN 1 = JD 2444239.5  TAI-UTC = 19.0
+ 1981 JUL 1 = JD 2444786.5  TAI-UTC = 20.0
+ 1982 JUL 1 = JD 2445151.5  TAI-UTC = 21.0
+ 1983 JUL 1 = JD 2445516.5  TAI-UTC = 22.0
+ 1985 JUL 1 = JD 2446247.5  TAI-UTC = 23.0
+ 1988 JAN 1 = JD 2447161.5  TAI-UTC = 24.0
+ 1990 JAN 1 = JD 2447892.5  TAI-UTC = 25.0
+ 1991 JAN 1 = JD 2448257.5  TAI-UTC = 26.0
+ 1992 JUL 1 = JD 2448804.5  TAI-UTC = 27.0
+ 1993 JUL 1 = JD 2449169.5  TAI-UTC = 28.0
+ 1994 JUL 1 = JD 2449534.5  TAI-UTC = 29.0
+ 1996 JAN 1 = JD 2450083.5  TAI-UTC = 30.0
+ 1997 JUL 1 = JD 2450630.5  TAI-UTC = 31.0
+ 1999 JAN 1 = JD 2451179.5  TAI-UTC = 32.0
+*/
+
+// Table for Julian date of leapsecond update and current total number of leapseconds at that date
+static double leapseconds[NUM_LEAPSECOND_UPDATES][2] = {
+            {
+                2441317.5, 10.0},
+            {
+                2441499.5, 11.0},
+            {
+                2441683.5, 12.0},
+            {
+                2442048.5, 13.0},
+            {
+                2442413.5, 14.0},
+            {
+                2442778.5, 15.0},
+            {
+                2443144.5, 16.0},
+            {
+                2443509.5, 17.0},
+            {
+                2443874.5, 18.0},
+            {
+                2444239.5, 19.0},
+            {
+                2444786.5, 20.0},
+            {
+                2445151.5, 21.0},
+            {
+                2445516.5, 22.0},
+            {
+                2446247.5, 23.0},
+            {
+                2447161.5, 24.0},
+            {
+                2447892.5, 25.0},
+            {
+                2448257.5, 26.0},
+            {
+                2448804.5, 27.0},
+            {
+                2449169.5, 28.0},
+            {
+                2449534.5, 29.0},
+            {
+                2450083.5, 30.0},
+            {
+                2450630.5, 31.0},
+            {
+                2451179.5, 32.0}
+        };
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psTime psTimeGetTime(void)
+{
+    struct timeval now;
+    psTime time;
+
+    time.tv_sec = 0;
+    time.tv_usec = 0;
+
+    if (gettimeofday(&now, (struct timezone *)0) == -1) {
+        psError(__func__, " : Line %d - Failed to get time", __LINE__);
+        return time;
+    }
+    // Convert timeval time to psTime
+    time.tv_sec = now.tv_sec;
+    time.tv_usec = now.tv_usec;
+
+    // Add most current leapseconds value to UTC time to get TAI time
+    time.tv_sec += leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+
+    return time;
+}
+
+char *psTimeToISO(psTime time)
+{
+    int ms = 0;
+    char *timeString = NULL;
+    char *tempString = NULL;
+    struct tm *tmTime = NULL;
+    time_t sec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, NULL);
+
+    tempString = psAlloc(MAX_TIME_STRING_LENGTH);
+    timeString = psAlloc(MAX_TIME_STRING_LENGTH);
+
+    // Converts psTime to YYYY/MM/DD,HH:MM:SS.SSS in string form
+    ms = time.tv_usec / 1000;
+
+    sec = time.tv_sec;
+    // tmTime variable is statically allocated, no need to free
+    tmTime = gmtime(&sec);
+    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
+        psError(__func__, " : Line %d - Failed strftime conversion", __LINE__);
+    }
+
+    if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3d", tempString, ms) < 0) {
+        psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
+    }
+    psFree(tempString);
+
+    return timeString;
+}
+
+psTime psTimeToUTC(psTime time)
+{
+    int i = 0;
+    double jd = 0.0;
+    double ls = 0.0;
+    double *jdTable = NULL;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, outTime);
+
+    // Find leapseconds to subtract from psTime to get UTC time
+    jd = psTimeToJD(time);
+    jdTable = leapseconds[0];
+    for (i = 0; i < NUM_LEAPSECOND_UPDATES; i++, jdTable += 2) {
+        if (jd > *jdTable) {
+            ls = *(jdTable + 1);
+        }
+    }
+
+    outTime.tv_sec = time.tv_sec - ls;
+    outTime.tv_usec = time.tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+double psTimeToMJD(psTime time)
+{
+    double mjd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, mjd);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    mjd = time.tv_sec / SEC_PER_DAY + time.tv_usec / USEC_PER_DAY + 40587.0;
+
+    return mjd;
+}
+
+double psTimeToJD(psTime time)
+{
+    double jd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, jd);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    jd = time.tv_sec / SEC_PER_DAY + time.tv_usec / USEC_PER_DAY + 2440587.5;
+
+    return jd;
+}
+
+struct timeval psTimeToTimeval(psTime time)
+{
+    struct timeval timevalTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, timevalTime);
+    timevalTime.tv_sec = time.tv_sec;
+    timevalTime.tv_usec = time.tv_usec;
+
+    return timevalTime;
+}
+
+struct tm *psTimeToTM(psTime time)
+{
+    struct tm *tmTime = NULL;
+    time_t sec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, tmTime);
+    sec = time.tv_sec;
+    tmTime = gmtime(&sec);
+
+    return tmTime;
+}
+
+psTime psISOToTime(char *time)
+{
+    char tempString[MAX_TIME_STRING_LENGTH];
+    int month;
+    int day;
+    int year;
+    int hour;
+    int minute;
+    int second;
+    int millisecond;
+    struct tm tmTime;
+    psTime outTime;
+
+    strncpy(tempString, time, MAX_TIME_STRING_LENGTH);
+
+    // Convert YYYY/MM/DD,HH:MM:SS.SSS in string form to tm time
+    year = atoi(strtok(tempString, "/"));
+    if (year < 1900) {
+        psError(__func__, "Years less than 1900 not allowed. Value: %d", year);
+        return outTime;
+    }
+
+    month = atoi(strtok(NULL, "/"));
+    if (month < 1 || month > 12) {
+        psError(__func__, "Month must have a value from 1 to 12. Value: %d", month);
+        return outTime;
+    }
+
+    day = atoi(strtok(NULL, ","));
+    if (day < 1 || day > 31) {
+        psError(__func__, "Day must have a value from 1 to 31. Value: %d", day);
+        return outTime;
+    }
+
+    hour = atoi(strtok(NULL, ":"));
+    if (hour < 0 || hour > 23) {
+        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", hour);
+        return outTime;
+    }
+
+    minute = atoi(strtok(NULL, ":"));
+    if (minute < 0 || minute > 59) {
+        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", minute);
+        return outTime;
+    }
+
+    second = atoi(strtok(NULL, "."));
+    if (second < 0 || second > 59) {
+        psError(__func__, "Second must have a value from 0 to 59. Value: %d", second);
+        return outTime;
+    }
+
+    millisecond = atoi(strtok(NULL, "X"));
+    if (millisecond < 0 || millisecond > 1000) {
+        psError(__func__, "Millisecond must have a value from 0 to 999. Value: %d", millisecond);
+        return outTime;
+    }
+
+    tmTime.tm_year = year - 1900;
+    tmTime.tm_mon = month - 1;
+    tmTime.tm_mday = day;
+    tmTime.tm_hour = hour;
+    tmTime.tm_min = minute;
+    tmTime.tm_sec = second;
+    tmTime.tm_isdst = -1;
+
+    // Convert tm time to psTime
+    outTime = psTMToTime(&tmTime);
+    outTime.tv_usec = millisecond * 1000;
+
+    return outTime;
+}
+
+psTime psUTCToTime(psTime time)
+{
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, outTime);
+
+    // Convert UTC time to psTime/TAI
+    outTime.tv_sec = time.tv_sec + leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+    outTime.tv_usec = time.tv_usec;
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psMJDToTime(double time)
+{
+    psTime outTime;
+    double days = 0.0;
+    double seconds = 0.0;
+
+    CHECK_NEGATIVE_TIME(time, outTime);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = time - 40587.0;
+
+    // Convert to psTime/TAI
+    seconds = days * SEC_PER_DAY;
+    outTime.tv_usec = (seconds - (long)seconds) * 1000000.0;
+    outTime.tv_sec = seconds;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME(time, outTime);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = time - 2440587.5;
+
+    // Convert to psTime/TAI
+    seconds = days * SEC_PER_DAY;
+    outTime.tv_sec = seconds;
+    outTime.tv_usec = (seconds - (long)seconds) * 1000000.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psTimevalToTime(struct timeval * time)
+{
+    psTime outTime;
+
+    if (time == NULL)
+    {
+        psError(__func__, "Null value for timeval arg not allowed");
+        return outTime;
+    } else if (time->tv_sec < 0)
+    {
+        psError(__func__, "Negative seconds are not allowed: %ld", time->tv_sec);
+        return outTime;
+    } else if (time->tv_usec < 0)
+    {
+        psError(__func__, "Negative microseconds are not allowed: %ld", time->tv_usec);
+        return outTime;
+    }
+    // Convert to psTime/TAI
+    outTime.tv_sec = time->tv_sec;
+    outTime.tv_usec = time->tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psTMToTime(struct tm * time)
+{
+    int i;
+    int n;
+    int y;
+    int mon[] = {
+                    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+                };
+    long epoch;
+    psTime outTime;
+
+    i = 0;
+    n = 0;
+    y = 0;
+    epoch = 0;
+
+    if (time == NULL)
+    {
+        psError(__func__, "Null value for tm arg not allowed");
+        return outTime;
+    } else if (time->tm_year < 70)
+    {
+        psError(__func__, "Input times earlier than 1970 not allowed. Value: %d", time->tm_year + 1900);
+        return outTime;
+    } else if (time->tm_mon < 0 || time->tm_mon > 11)
+    {
+        psError(__func__, "Month must have a value from 0 to 11. Value: %d", time->tm_mon);
+        return outTime;
+    } else if (time->tm_mday < 1 || time->tm_mday > 31)
+    {
+        psError(__func__, "Day must have a value from 1 to 31. Value: %d", time->tm_mday);
+        return outTime;
+    } else if (time->tm_hour < 0 || time->tm_hour > 23)
+    {
+        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", time->tm_hour);
+        return outTime;
+    } else if (time->tm_min < 0 || time->tm_min > 59)
+    {
+        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", time->tm_min);
+        return outTime;
+    } else if (time->tm_sec < 0 || time->tm_sec > 59)
+    {
+        psError(__func__, "Second must have a value from 0 to 59. Value: %d", time->tm_sec);
+        return outTime;
+    }
+
+    n = time->tm_year + 1900 - 1;
+    epoch = (time->tm_year - 70) * SEC_PER_YEAR + ((n / 4 - n / 100 + n / 400) -
+            (1969 / 4 - 1969 / 100 + 1969 / 400)) * SEC_PER_DAY;
+
+    y = time->tm_year + 1900;
+
+    // Adjust for leap years
+    for (i = 0; i < time->tm_mon; i++)
+    {
+        epoch += mon[i] * SEC_PER_DAY;
+        if (i == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
+            epoch += SEC_PER_DAY;
+        }
+    }
+
+    // Add everything
+    epoch += (time->tm_mday - 1) * SEC_PER_DAY;
+    epoch += time->tm_hour * SEC_PER_HOUR + time->tm_min * SEC_PER_MINUTE + time->tm_sec;
+
+    // Create psTime
+    outTime.tv_usec = 0;
+    outTime.tv_sec = epoch;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
Index: /tags/rel2_1/psLib/src/astro/psTime.h
===================================================================
--- /tags/rel2_1/psLib/src/astro/psTime.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astro/psTime.h	(revision 1553)
@@ -0,0 +1,203 @@
+
+/** @file  psTime.h
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy
+ *  functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
+ *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
+ *  base upon which International Atomic Time (TAI) time is calculated. All time conversion functions within
+ *  psLib, except those noted, are calculated in terms of TAI time, which is approxinmately 32 seconds faster
+ *  than UTC/timeval.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-13 22:08:51 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSTIME_H
+#define PSTIME_H
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "psType.h"
+
+/// @addtogroup Time
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Definition of psTime.
+ *
+ *  The psTime struct is used by psLib to represent time values critical to 
+ *  astronomical calculations.  This structure represents a time which is 
+ *  equivalent to TAI (International Atomic Time) and is measured in both 
+ *  seconds and microseconds.
+ */
+typedef struct timeval psTime;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Get current TAI time.
+ *
+ * Gets current time from the system clock in correct TAI units.
+ *
+ *  @return  psTime: Struct with current time.
+ */
+
+psTime psTimeGetTime(void);
+
+/** Convert psTime to ISO time in TAI units.
+ *
+ *  Converts psTime to a null terminated string in the form of: 
+ *  YYYY/MM/DD,HH:MM:SS.SSS. This function assumes the input time already is 
+ *  in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  char*: Pointer null terminated array of chars in ISO time.
+ */
+
+char *psTimeToISO(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to UTC time.
+ *
+ *  Converts psTime to UTC time in double precision floating point notation. 
+ *  The input to this must already be int TAI time. The result from this 
+ *  function is not in TAI units, but that of UTC, which does not contain
+ *  leapseconds.
+ *
+ *  @return  psTime: UTC time psTime format.
+ */
+
+psTime psTimeToUTC(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to modified Julian date time.
+ *
+ *  Converts psTime to modified Julian date (MJD) time. This function assumes 
+ *  the input time already is in TAI time and does not add or subtract 
+ *  leapseconds.
+ *
+ *  @return  double: Modified Julian Days (MJD) time.
+ */
+double psTimeToMJD(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to Julian date time.
+ *
+ *  Converts psTime to Julian date (JD) time. This function assumes the input 
+ *  time already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  double: Julian Date (JD) time.
+ */
+double psTimeToJD(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to timeval time.
+ *
+ *  Converts psTime to timeval time. This function assumes the input time 
+ *  already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  timeval: timeval struct time.
+ */
+struct timeval psTimeToTimeval(
+                psTime time                        ///< Input time to be converted.
+            );
+
+/** Convert psTime to tm time.
+ *
+ * Converts psTime to tm time. This function assumes the input time already is in TAI time and does not add or
+ * subtract leapseconds.
+ *
+ *  @return  tm: tm struct time.
+ */
+struct tm *psTimeToTM(
+                psTime time                        ///< Input time to be converted.
+            );
+
+/** Convert ISO to psTime.
+ *
+ *  Converts ISO time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time
+ */
+psTime psISOToTime(
+    char *time                         ///< Input time to be converted.
+);
+
+/** Convert UTC to psTime.
+ *
+ *  Converts UTC time to psTime. This function assumes the input time already 
+ *  is in TAI time and add or subtracts the necessary leapseconds.
+ *
+ *  @return  psTime: time in TAI units.
+ */
+psTime psUTCToTime(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert MJD to psTime.
+ *
+ *  Converts MJD time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psMJDToTime(
+    double time                        ///< Input time to be converted.
+);
+
+/** Convert JD to psTime.
+ *
+ *  Converts JD time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psJDToTime(
+    double time                        ///< Input time to be converted.
+);
+
+/** Convert timeval to psTime.
+ *
+ *  Converts timeval time to psTime. This function assumes the input time 
+ *  already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psTimevalToTime(
+    struct timeval *time               ///< Input time to be converted.
+);
+
+/** Convert tm time to psTime.
+ *
+ *  Converts tm time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psTMToTime(
+    struct tm *time                    ///< Input time to be converted.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/Makefile	(revision 1553)
@@ -0,0 +1,55 @@
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+TARGET_STATIC  = libpslib.a
+include ../Makefile.Globals
+CFLAGS := $(CFLAGS_RELOC) -I. -I../sysUtils -I../collections -I../dataManip -I.. -I../image
+
+SRC_OBJS = psTime.o \
+           psMetadata.o \
+           psCoord.o \
+           psAstrometry.o
+
+OBJS = $(addprefix makedir/,$(SRC_OBJS))
+
+all: $(TARGET_STATIC)
+
+# Rule to make static library
+
+libpslib.a:     $(OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs ../$@ $(OBJS)
+
+# Define PHONY target "install" which will install necessary files
+install: $(TARGET_STATIC)
+	install *.h $(includedir)
+
+# Define PHONY target "distclean" which will cleanup the distribution
+distclean:      clean
+	$(RM) ../$(TARGET_STATIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+clean:
+	@echo "    Deleting intermediate files for 'astronomy'"
+	$(RM) $(OBJS) *.lint $(SRC_OBJS:.o=.i)
+
+cleandep:
+	$(RM) $(OBJS:.o=.d)
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+%.i: %.c
+	$(CC) -E $(CFLAGS) -o $@ $<
+
+makedir/%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+makedir/%.d: %.c
+	$(CC) -MM $(CFLAGS) $< > $@.tmp
+	sed 's|\($*\)\.o[ :]*|\1.o $@ : |g' $@.tmp > $@
+	$(RM) -f $@.tmp
+
+include $(OBJS:.o=.d)
Index: /tags/rel2_1/psLib/src/astronomy/psAstrometry.c
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psAstrometry.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psAstrometry.c	(revision 1553)
@@ -0,0 +1,665 @@
+/** @file  psAstrometry.c
+*
+*  @brief This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup AstroImage
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-14 01:51:11 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include<math.h>
+#include "psFunctions.h"
+#include "psAstrometry.h"
+#include "psMemory.h"
+#include "psAbort.h"
+#include "slalib.h"
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+void p_psGrommitFree(psGrommit* grommit)
+{
+    psFree(grommit);
+}
+
+/*****************************************************************************
+p_psCheckValidImageCoords(): this is a private function which simply
+determines if the supplied x,y coordinates are in the range for the supplied
+psImage.
+ *****************************************************************************/
+int p_psCheckValidImageCoords(double x,
+                              double y,
+                              psImage* tmpImage)
+{
+    if (tmpImage == NULL) {
+        return(0);
+    }
+
+    if ((x < 0.0) ||
+            (x > (double)tmpImage->numCols) ||
+            (y < 0.0) ||
+            (y > (double)tmpImage->numRows)) {
+        return (0);
+    }
+
+    return (1);
+}
+
+/*****************************************************************************
+p_psIsProjectionLinear(): this is a private function which simply determines
+if the supplied psPlaneTransform transform is linear: if any of the
+cooefficients of order 2 are higher are non-zero, then it is not linear.
+ *****************************************************************************/
+int p_psIsProjectionLinear(psPlaneTransform *transform)
+{
+    int i = 0;
+    if (transform == NULL) {
+        psAbort(__func__, "input parameter transform is NULL.");
+    }
+
+    for (i=2;i<(transform->x->nX);i++) {
+        if (transform->x->coeff[i][0] != 0.0) {
+            return(0);
+        }
+    }
+    for (i=2;i<(transform->x->nY);i++) {
+        if (transform->x->coeff[0][i] != 0.0) {
+            return(0);
+        }
+    }
+
+    for (i=2;i<(transform->y->nX);i++) {
+        if (transform->y->coeff[i][0] != 0.0) {
+            return(0);
+        }
+    }
+    for (i=2;i<(transform->y->nY);i++) {
+        if (transform->y->coeff[0][i] != 0.0) {
+            return(0);
+        }
+    }
+
+    return(1);
+}
+
+/*****************************************************************************
+p_psInvertPlaneTransform(transform): : this is a private function which
+simply inverts the supplied psPlaneTransform transform.  It assumes that
+"transform" is linear.
+ 
+This program assumes that the inverse of the following linear equations:
+        X2 = A + (B * X1) + (C * Y1);
+        Y2 = D + (E * X1) + (F * Y1);
+is
+        Y1 = (Y2 - ((E/B) * X2) - D + ((E*A)/B)) / (F - ((C*E)/B));
+        X1 = (Y2 - ((F/C) * X2) - D + ((F*A)/C)) / (E - ((F*B)/C));
+or
+ X1 = (-D + ((F*A)/C)) / (E - ((F*B)/C)) +
+      (X2 * -((F/C) / (E - ((F*B)/C)))) +
+             (Y2 * (1.0 / (E - ((F*B)/C))));
+        Y1 = (-D + ((E*A)/B))/(F - ((C*E)/B)) +
+             (X2 * -((E/B) / (F - ((C*E)/B)))) +
+             (Y2 * (1.0 / (F - ((C*E)/B))));
+ *****************************************************************************/
+psPlaneTransform *p_psInvertPlaneTransform(psPlaneTransform *transform)
+{
+    double A = transform->x->coeff[0][0];
+    double B = transform->x->coeff[1][0];
+    double C = transform->x->coeff[0][1];
+    double D = transform->y->coeff[0][0];
+    double E = transform->y->coeff[1][0];
+    double F = transform->y->coeff[0][1];
+
+    if (transform == NULL) {
+        psAbort(__func__, "input parameter transform is NULL.");
+    }
+    psPlaneTransform *out = psAlloc(sizeof(psPlaneTransform));
+
+    out->x->coeff[0][0] = -D + ((F*A)/C) / (E - ((F*B)/C));
+    out->x->coeff[1][0] = -(F/C) / (E - ((F*B)/C));
+    out->x->coeff[0][1] =  1.0 / (E - ((F*B)/C));
+    out->y->coeff[0][0] = -D + ((E*A)/B) / (F - ((C*E)/B));
+    out->y->coeff[1][0] = -(E/B) / (F - ((C*E)/B));
+    out->y->coeff[0][1] =  1.0 / (F - ((C*E)/B));
+
+    return(out);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+psExposure* psExposureAlloc(double ra, double dec, double hourAngle,
+                            double zenith, double azimuth, double localTime, float date,
+                            float rotAngle, float temperature, float pressure, float humidity,
+                            float exposureTime)
+{
+    psExposure* exp = psAlloc(sizeof(psExposure));
+
+    *(double *)&exp->ra = ra;
+    *(double *)&exp->dec = dec;
+    *(double *)&exp->hourAngle = hourAngle;
+    *(double *)&exp->zenith = zenith;
+    *(double *)&exp->azimuth = azimuth;
+    *(double *)&exp->localTime = localTime;
+    *(float *)&exp->date = date;
+    *(float *)&exp->rotAngle = rotAngle;
+    *(float *)&exp->temperature = temperature;
+    *(float *)&exp->pressure = pressure;
+    *(float *)&exp->humidity = humidity;
+    *(float *)&exp->exposureTime = exposureTime;
+
+    return exp;
+}
+#define TBD 0.0
+/*****************************************************************************
+XXX: Several of the input params to sla_aoppa() are currently undefined.
+We are awaiting futher direction from IfA on this.
+ *****************************************************************************/
+psGrommit* psGrommitAlloc(const psExposure* exp)
+{
+    if (exp == NULL) {
+        psAbort(__func__, "the 'exp' parameter is NULL\n");
+    }
+
+    double date = TBD;  // "mjd" in psExposure will become a psTime
+    // from which it will be possible to get UTC.
+    double dut = 0.0;
+    double elongm = TBD;
+    double phim = TBD;
+    double hm = TBD;
+    double xp = 0.0;
+    double yp = 0.0;
+    double tdk = exp->temperature;
+    double pmb = exp->pressure;
+    double rh = exp->humidity;
+    double wl = exp->wavelength;
+    double tlr = TBD;
+    double *AOPRMS = NULL;
+
+    slaAoppa(date, dut, elongm, phim, hm, xp, yp,
+             tdk, pmb, rh, wl, tlr, AOPRMS);
+
+    psGrommit* grommit = (psGrommit* ) psAlloc(sizeof(psGrommit));
+    *(double *)&grommit->latitude = AOPRMS[0];
+    *(double *)&grommit->sinLat = AOPRMS[1];
+    *(double *)&grommit->cosLat = AOPRMS[2];
+    *(double *)&grommit->height = AOPRMS[3];
+    *(double *)&grommit->abberationMag = AOPRMS[4];
+    *(double *)&grommit->temperature = AOPRMS[5];
+    *(double *)&grommit->pressure = AOPRMS[6];
+    *(double *)&grommit->humidity = AOPRMS[7];
+    *(double *)&grommit->wavelength = AOPRMS[8];
+    *(double *)&grommit->lapseRate = AOPRMS[9];
+    *(double *)&grommit->refractA = AOPRMS[10];
+    *(double *)&grommit->refractB = AOPRMS[11];
+    *(double *)&grommit->longitudeOffset = AOPRMS[12];
+    *(double *)&grommit->siderealTime = AOPRMS[13];
+
+    return (grommit);
+}
+
+psCell* psCellInFPA(const psPlane* fpaCoord,
+                    const psFPA* FPA)
+{
+    psChip* tmpChip = NULL;
+    psPlane* chipCoord = NULL;
+    psCell* outCell = NULL;
+
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
+    if (FPA == NULL) {
+        psAbort(__func__, "input parameter FPA is NULL.");
+    }
+
+    // Determine which chip contains the fpaCoords.
+    tmpChip = psChipInFPA(fpaCoord, FPA);
+
+    // Convert to those chip coordinates.
+    chipCoord = psCoordFPAToChip(chipCoord, fpaCoord, tmpChip);
+
+    // Determine which cell contains those chip coordinates.
+    outCell = psCellInChip(chipCoord, tmpChip);
+
+    psFree(tmpChip);
+    psFree(chipCoord);
+
+    return (outCell);
+}
+
+psChip* psChipInFPA(const psPlane* fpaCoord,
+                    const psFPA* FPA)
+{
+    psArray* chips = FPA->chips;
+    int nChips = chips->n;
+    psPlane* chipCoord = NULL;
+    psCell *tmpCell = NULL;
+
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
+    if (FPA == NULL) {
+        psAbort(__func__, "input parameter FPA is NULL.");
+    }
+
+    // Loop through every chip in this FPA.  Convert the original
+    // FPA coordinates to chip coordinates for that chip.  Then,
+    // determine if any cells in that chip contain those chip
+    // coordinates.
+    for (int i = 0; i < nChips; i++) {
+        psChip* tmpChip = chips->data[i];
+        chipCoord = psPlaneTransformApply(chipCoord, tmpChip->fromFPA,
+                                          fpaCoord);
+
+        tmpCell = psCellInChip(chipCoord, tmpChip);
+        if (tmpCell != NULL) {
+            psFree(chipCoord);
+            return(tmpChip);
+        }
+        psFree(chipCoord);
+    }
+
+    return (NULL);
+}
+
+psCell* psCellInChip(const psPlane* chipCoord,
+                     const psChip* chip)
+{
+    psPlane* cellCoord = NULL;
+    psArray* cells;
+
+    // We return NULL if either of the input parameters is NULL.
+    if (chipCoord == NULL) {
+        psAbort(__func__, "the 'chipCoord' parameter is NULL\n");
+    }
+    if (chip == NULL) {
+        psAbort(__func__, "the 'chip' parameter is NULL\n");
+    }
+
+    cells = chip->cells;
+    if (cells == NULL) {
+        return NULL;
+    }
+
+    // We loop over each cell in the chip.  We transform the chipCoord into
+    // a cellCoord for that cell and determine if that cellCoord is valid.
+    // If so, then we return that cell.
+    for (int i = 0; i < cells->n; i++) {
+        psCell* tmpCell = (psCell* ) cells->data[i];
+        psArray* readouts = tmpCell->readouts;
+
+        if (readouts != NULL) {
+            for (int j = 0; j < readouts->n; j++) {
+                psReadout* tmpReadout = readouts->data[j];
+
+                cellCoord = psPlaneTransformApply(cellCoord,
+                                                  tmpCell->fromChip,
+                                                  chipCoord);
+
+                if (p_psCheckValidImageCoords(cellCoord->x,
+                                              cellCoord->y,
+                                              tmpReadout->image)) {
+                    psFree(cellCoord);
+                    return (tmpCell);
+                }
+            }
+        }
+    }
+
+    psFree(cellCoord);
+    return (NULL);
+}
+
+psPlane* psCoordCellToChip(psPlane* outCoord,
+                           const psPlane* inCoord,
+                           const psCell* cell)
+{
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    return (psPlaneTransformApply(outCoord, cell->toChip, inCoord));
+}
+
+psPlane* psCoordChipToFPA(psPlane* outCoord,
+                          const psPlane* inCoord,
+                          const psChip* chip)
+{
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (chip == NULL) {
+        psAbort(__func__, "input parameter chip is NULL.");
+    }
+
+    return (psPlaneTransformApply(outCoord, chip->toFPA, inCoord));
+}
+
+psPlane* psCoordFPAToTP(psPlane* outCoord,
+                        const psPlane* inCoord,
+                        double color,
+                        double magnitude,
+                        const psFPA* fpa)
+{
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (fpa == NULL) {
+        psAbort(__func__, "input parameter fpa is NULL.");
+    }
+
+    return(psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord,
+                               color, magnitude));
+}
+
+/*****************************************************************************
+XXX: What about units for the (x,y) coords?
+ *****************************************************************************/
+psSphere* psCoordTPToSky(psSphere* outSphere,
+                         const psPlane* tpCoord,
+                         const psGrommit* grommit)
+{
+    double AOB = 0.0;
+    double ZOB = 0.0;
+    double HOB = 0.0;
+
+    if (tpCoord == NULL) {
+        psAbort(__func__, "input parameter tpCoord is NULL.");
+    }
+    if (grommit == NULL) {
+        psAbort(__func__, "input parameter grommit is NULL.");
+    }
+    if (outSphere == NULL) {
+        outSphere = (psSphere* ) psAlloc(sizeof(psSphere));
+    }
+
+    slaAopqk(tpCoord->x, tpCoord->y, (double *) grommit,
+             &AOB, &ZOB, &HOB, &outSphere->r, &outSphere->d);
+
+    return (outSphere);
+}
+
+psPlane* psCoordCellToFPA(psPlane* fpaCoord,
+                          const psPlane* cellCoord,
+                          const psCell* cell)
+{
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    return (psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord));
+}
+
+psSphere* psCoordCellToSky(psSphere* skyCoord,
+                           const psPlane* cellCoord,
+                           double color,
+                           double magnitude,
+                           const psCell* cell)
+{
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psPlane* fpaCoord = NULL;
+    psPlane* tpCoord = NULL;
+    psFPA* parFPA = (cell->parent)->parent;
+    psGrommit* tmpGrommit = NULL;
+
+    // Convert the input cell coordinates to FPA coordinates.
+    fpaCoord = psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord);
+
+    // Convert the FPA coordinates to tangent plane Coordinates.
+    tpCoord = psPlaneDistortApply(tpCoord, parFPA->toTangentPlane,
+                                  fpaCoord, color, magnitude);
+
+    // Generate a grommit for this FPA.
+    tmpGrommit = psGrommitAlloc(parFPA->exposure);
+
+    // Convert the tangent plane Coordinates to sky coordinates.
+    skyCoord = psCoordTPToSky(skyCoord, tpCoord, tmpGrommit);
+
+    psFree(fpaCoord);
+    psFree(tpCoord);
+    psFree(tmpGrommit);
+
+    return(skyCoord);
+}
+
+psSphere* psCoordCellToSkyQuick(psSphere* outSphere,
+                                const psPlane* cellCoord,
+                                const psCell* cell)
+{
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psPlane *tpCoord = NULL;
+    psChip *chip = cell->parent;
+    psFPA *FPA = chip->parent;
+    psProjectionType oldProjectionType;
+
+    if (outSphere == NULL) {
+        outSphere = (psSphere* ) psAlloc(sizeof(psSphere));
+    }
+
+    // Determine the tangent plane coordinates.
+    tpCoord = psPlaneTransformApply(tpCoord, cell->toTP, cellCoord);
+
+    // Save the old projection type and set the new projection type to TAN.
+    oldProjectionType = FPA->projection->type;
+    FPA->projection->type = PS_PROJ_TAN;
+
+    // Deproject the tangent plane coordinates a sphere.
+    outSphere = psDeproject(tpCoord, FPA->projection);
+
+    // Restore old projection type.  Free memory.
+    FPA->projection->type = oldProjectionType;
+    psFree(tpCoord);
+
+    return (outSphere);
+}
+
+/*****************************************************************************
+XXX: What about units for the (x,y) coords?
+ *****************************************************************************/
+psPlane* psCoordSkyToTP(psPlane* tpCoord,
+                        const psSphere* in,
+                        const psGrommit* grommit)
+{
+    if (in == NULL) {
+        psAbort(__func__, "input parameter in is NULL.");
+    }
+    if (grommit == NULL) {
+        psAbort(__func__, "input parameter grommit is NULL.");
+    }
+    if (tpCoord == NULL) {
+        tpCoord = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+
+    slaOapqk("RA", in->r, in->d, (double *) grommit, &tpCoord->x, &tpCoord->y);
+
+    return(tpCoord);
+}
+
+
+psPlane* psCoordTPToFPA(psPlane* fpaCoord,
+                        const psPlane* tpCoord,
+                        double color,
+                        double magnitude,
+                        const psFPA* fpa)
+{
+    if (tpCoord == NULL) {
+        psAbort(__func__, "input parameter tpCoord is NULL.");
+    }
+    if (fpa == NULL) {
+        psAbort(__func__, "input parameter fpa is NULL.");
+    }
+
+    return (psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane,
+                                tpCoord, color, magnitude));
+}
+
+psPlane* psCoordFPAToChip(psPlane* chipCoord,
+                          const psPlane* fpaCoord,
+                          const psChip* chip)
+{
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
+    if (chip == NULL) {
+        psAbort(__func__, "input parameter chip is NULL.");
+    }
+
+    psFPA *FPA = chip->parent;
+    if (FPA == NULL) {
+        psAbort(__func__, "chip->parent is NULL");
+    }
+
+    chipCoord = psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord);
+
+    return(chipCoord);
+}
+
+psPlane* psCoordChipToCell(psPlane* cellCoord,
+                           const psPlane* chipCoord,
+                           const psCell* cell)
+{
+    if (chipCoord == NULL) {
+        psAbort(__func__, "input parameter chipCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psChip *chip = cell->parent;
+    if (chip == NULL) {
+        psAbort(__func__, "cell->parent is NULL");
+    }
+
+    cellCoord = psPlaneTransformApply(cellCoord, cell->fromChip, chipCoord);
+
+    return(cellCoord);
+}
+
+psPlane* psCoordSkyToCell(psPlane* cellCoord,
+                          const psSphere* skyCoord,
+                          double color,
+                          double magnitude,
+                          const psCell* cell)
+{
+    if (skyCoord == NULL) {
+        psAbort(__func__, "input parameter skyCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psChip *parChip = cell->parent;
+    psFPA *parFPA = parChip->parent;
+    psGrommit* grommit = parFPA->grommit;
+
+    // Convert the skyCoords to tangent plane coords.
+    psPlane *tpCoord = psCoordSkyToTP(tpCoord, skyCoord, grommit);
+
+    // Convert the tangent plane coords to FPA coords.
+    psPlane *fpaCoord = psCoordTPToFPA(fpaCoord, tpCoord, color,
+                                       magnitude, parFPA);
+
+    // Convert the FPA coords to chip coords.
+    psPlane *chipCoord = psCoordFPAToChip(chipCoord, fpaCoord, parChip);
+
+    // Convert the chip coords to cell coords.
+    cellCoord = psCoordChipToCell(cellCoord, chipCoord, cell);
+
+    psFree(tpCoord);
+    psFree(fpaCoord);
+    psFree(chipCoord);
+
+    return (cellCoord);
+}
+
+psPlane* psCoordSkyToCellQuick(psPlane* cellCoord,
+                               const psSphere* skyCoord,
+                               const psCell* cell)
+{
+    if (skyCoord == NULL) {
+        psAbort(__func__, "input parameter skyCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psPlane *tpCoord = NULL;
+    psChip *whichChip = cell->parent;
+    psFPA *whichFPA = whichChip->parent;
+    psProjectionType oldProjectionType;
+    psPlaneTransform *TPtoCell = NULL;
+
+    // Save the old projection type and set the new projection type to TAN.
+    oldProjectionType = whichFPA->projection->type;
+    whichFPA->projection->type = PS_PROJ_TAN;
+
+    if (cellCoord == NULL) {
+        cellCoord = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+
+    tpCoord = psProject(skyCoord, whichFPA->projection);
+
+    // generate an error if cell->toTP is not linear.
+    if (0 == p_psIsProjectionLinear(cell->toTP)) {
+        psAbort(__func__, "the cell->toTP transfrom is not linear.\n");
+    }
+
+    TPtoCell = p_psInvertPlaneTransform(cell->toTP);
+    cellCoord = psPlaneTransformApply(cellCoord, TPtoCell, tpCoord);
+
+    // Restore old projection type.  Free memory.
+    whichFPA->projection->type = oldProjectionType;
+    psFree(tpCoord);
+    return (cellCoord);
+}
+
Index: /tags/rel2_1/psLib/src/astronomy/psAstrometry.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psAstrometry.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psAstrometry.h	(revision 1553)
@@ -0,0 +1,422 @@
+/** @file  psAstrometry.h
+*
+*  @brief This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup AstroImage
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-13 22:41:24 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_ASTROMETRY_H
+#define PS_ASTROMETRY_H
+
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psFunctions.h"
+#include "psMetadata.h"
+#include "psCoord.h"
+#include "psPhotometry.h"
+
+struct psCell;
+struct psChip;
+struct psFPA;
+struct psExposure;
+
+/// @addtogroup AstroImage
+/// @{
+
+/** Wallace's Grommit
+ *
+ *  SLALib requires several elements to perform the transformations between
+ *  the tangent plane and the sky.  Pre-computing these quantities for each
+ *  exposure means that subsequent transformations are faster.  For historical
+ *  reasons, this structure is known colloquially as "Wallace's Grommit".
+ *  
+ */
+typedef struct
+{
+    const double latitude;             ///< geodetic latitude (radians)
+    const double sinLat;               ///< sine of geodetic latitude
+    const double cosLat;               ///< cosine of geodetic latitude
+    const double abberationMag;        ///< magnitude of diurnal aberration vector
+    const double height;               ///< height (HM)
+    const double temperature;          ///< ambient temperature (TDK)
+    const double pressure;             ///< pressure (PMB)
+    const double humidity;             ///< relative humidity (RH)
+    const double wavelength;           ///< wavelength (WL)
+    const double lapseRate;            ///< lapse rate (TLR)
+    const double refractA;             ///< refraction constant A (radians)
+    const double refractB;             ///< refraction constant B (radians)
+    const double longitudeOffset;      ///< longitude + ... (radians)
+    const double siderealTime;         ///< local apparent sidereal time (radians)
+}
+psGrommit;
+
+/** Fixed Pattern Corrections
+ *
+ *  The fixed pattern is a correction to the general astrometric solution 
+ *  formed by summing the residuals from many observations. The intent is to 
+ *  correct for higher-order distortions in the camera system on a coarse 
+ *  grid (larger than individual pixels, but smaller than a single cell). 
+ *  Hence, in addition to the offsets, we need to specify the size and scale 
+ *  of the grid in x and y as well as the origin of the grid.
+ */
+typedef struct
+{
+    int nX;                            ///< Number of elements in x direction
+    int nY;                            ///< Number of elements in y direction
+    double x0;                         ///< X Position of 0,0 corner on focal plane
+    double y0;                         ///< Y Position of 0,0 corner on focal plane
+    double xScale;                     ///< Scale of the grid in x direction
+    double yScale;                     ///< Scale of the grid in x direction
+    double **x;                        ///< The grid of offsets in x
+    double **y;                        ///< The grid of offsets in y
+}
+psFixedPattern;
+
+/** Readout data structure.
+ *
+ *  A readout is the result of a single read of a cell (or a portion thereof). 
+ *  It contains a pointer to the pixel data, and additional pointers to the 
+ *  objects found in the readout, and the readout metadata.  It also contains
+ *  the offset from the lower-left corner of the chip, in the case that the
+ *  CCD was windowed.
+ *
+ */
+typedef struct
+{
+    const unsigned int colBins;        ///< Amount of binning in x-dimension
+    const unsigned int rowBins;        ///< Amount of binning in y-dimension
+    const int col0;                    ///< Offset from the left of chip.
+    const int row0;                    ///< Offset from the bottom of chip.
+
+    psImage* image;                    ///< imaging area of Readout
+    psList* objects;                   ///< objects derived from Readout
+    psMetadata* metadata;              ///< readout-level metadata
+}
+psReadout;
+
+/** Cell data structure
+ * 
+ *  A cell consists of one or more readouts.  It also contains a pointer to the
+ *  cell's metadata, and its parent chip.  On the astrometry side, it also 
+ *  contains coordinate transforms from the cell to chip, from the cell to 
+ *  focal-plane, as well as a "quick and dirty" tranform from the cell to
+ *  sky coordinates.
+ *
+ */
+typedef struct psCell
+{
+    psArray* readouts;                 ///< readouts from the cell
+    psMetadata* metadata;              ///< cell-level metadata
+
+    psPlaneTransform* toChip;          ///< transformations from cell to chip coordinates
+    psPlaneTransform* fromChip;        ///< transformations from chip to cell coordinates
+    psPlaneTransform* toFPA;           ///< transformations from cell to FPA coordinates
+    psPlaneTransform* toTP;            ///< transformations from cell to tangent plane coordinates
+
+    struct psChip* parent;             ///< chip in which contains this cell
+}
+psCell;
+
+/** Chip data structure
+ *
+ *  A chip consists of one or more cells (according to the number of amplifiers
+ *  on the CCD). It contains a pointer to the chip's metadata, and a pointer
+ *  to the parent focal plane.  For astrometry, it contains a coordinate
+ *  transform from the chip to the focal plane, and vis-versa.
+ *
+ */
+typedef struct psChip
+{
+    psArray* cells;                    ///< cells in the chip
+    psMetadata* metadata;              ///< chip-level metadata
+
+    psPlaneTransform* toFPA;           ///< transformation from chip to FPA coordinates
+    psPlaneTransform* fromFPA;         ///< transformation from FPA to chip coordinates
+
+    struct psFPA* parent;              ///< FPA which contains this chip
+}
+psChip;
+
+/** A Focal-Plane
+ *
+ *  A focal plane consists of one or more chips (according to the number of
+ *  contiguous silicon).  It contains pointers to the focal-plane's metadata
+ *  and the exposure information.  For astrometry, it contains a transformation
+ *  from the focal plane to the tangent plane and the fixed pattern residuals.
+ *  Since colors are involved in the transformation, it is necessary to specify
+ *  the color the transformation is defined.  We also include some values to
+ *  characterize the quality of the transformation: the root square deviation
+ *  for the x and y transformation fits, and the chi-squared for the 
+ *  transformation fit.
+ *
+ */
+typedef struct psFPA
+{
+    psArray* chips;                    ///< chips in the focal plane array
+    psMetadata* metadata;              ///< focal-plane's metadata
+
+    psPlaneDistort* fromTangentPlane;  ///< transformation from tangent plane to focal plane
+    psPlaneDistort* toTangentPlane;    ///< transformation from focal plane to tangent plane
+    psFixedPattern* pattern;           ///< fixed pattern residual offsets
+
+    const struct psExposure* exposure; ///< information about this exposure
+    psGrommit *grommit;                ///< Wallace's grommit
+
+    psPhotSystem* colorPlus;           ///< Color reference
+    psPhotSystem* colorMinus;          ///< Color reference
+    psProjection *projection;          ///< projection
+
+    float rmsX;                        ///< RMS for x transformation fits
+    float rmsY;                        ///< RMS for y transformation fits
+    float chi2;                        ///< chi^2 of astrometric solution
+}
+psFPA;
+
+/** Exposure Information
+ *
+ *  Several quantities from the telescope in order to make a first guess at 
+ *  the astrometric solution.  From these quantities, further quantities can 
+ *  be derivedand stored for later use.
+ *
+ */
+typedef struct psExposure
+{
+    const double ra;                   ///< Telescope boresight, right ascention
+    const double dec;                  ///< Telescope boresight, declination
+    const double hourAngle;            ///< Hour angle
+    const double zenith;               ///< Zenith distance
+    const double azimuth;              ///< Azimuth
+    const double localTime;            ///< Local Sidereal Time
+    const float date;                  ///< Modified Jullian Date of observation
+    const float rotAngle;              ///< Rotator position angle
+    const float temperature;           ///< Air temperature, for estimating refraction
+    const float pressure;              ///< Air pressure, for calculating refraction
+    const float humidity;              ///< Relative humidity, for refraction
+    const float exposureTime;          ///< Exposure time
+    const double wavelength;           ///< Wavelength
+
+    /* Derived quantities */
+    const float positionAngle;         ///< Position angle
+    const float parallacticAngle;      ///< Parallactic angle
+    const float airmass;               ///< Airmass, calculated from zenith distance
+    const float parallacticFactor;     ///< Parallactic factor
+    const char *cameraName;            ///< name of camera which provided exposure
+    const char *telescopeName;         ///< name of telescope which provided exposure
+}
+psExposure;
+
+/** Allocator for psExposure
+ *
+ *  We need several quantities from the telescope in order to make a first 
+ *  guess at the astrometric solution. From these quantities, further 
+ *  quantities can be derived and stored for later use.
+ *
+ *  @return     psExposure*    new psExposure struct
+ */
+psExposure* psExposureAlloc(
+    double ra,                         ///< Telescope boresight, right ascention
+    double dec,                        ///< Telescope boresight, declination
+    double hourAngle,                  ///< Hour angle
+    double zenith,                     ///< Zenith distance
+    double azimuth,                    ///< Azimuth
+    double localTime,                  ///< Local Sidereal Time
+    float date,                        ///< MJD
+    float rotAngle,                    ///< Rotator position angle
+    float temperature,                 ///< Temperature
+    float pressure,                    ///< Pressure
+    float humidity,                    ///< Relative humidity
+    float exposureTime                 ///< Exposure time
+);
+
+/** Allocates a Wallace's Grommit structure.
+ *
+ *  The psGrommit is calculated from telescope information for the particular
+ *  exposure.
+ *
+ *  @return psGrommit* New grommit structure.
+ */
+psGrommit* psGrommitAlloc(const psExposure* exp        ///< the cooresponding exposure structure.
+                         );
+void p_psGrommitFree(psGrommit *grommit);
+psGrommit* psGrommitAlloc(
+    const psExposure* exp              ///< the cooresponding exposure structure.
+);
+
+/** Find cooresponding cell for given FPA coordinate
+ *
+ *  @return psCell*    the cell cooresponding to the coord in FPA
+ */
+psCell* psCellInFPA(
+    const psPlane* coord,              ///< the coordinate in FPA plane
+    const psFPA* FPA                   ///< the FPA to search for the cell
+);
+
+/** Find cooresponding chip for given FPA coordinate
+ *
+ *  @return psChip*    the chip cooresponding to coord
+ */
+psChip* psChipInFPA(
+    const psPlane* coord,              ///< the coordinate in FPA plane
+    const psFPA* FPA                   ///< the FPA to search for the cell
+);
+
+/** Find cooresponding cell for given Chip coordinate
+ *
+ *  @return psCell*    the cell cooresponding to coord
+ */
+psCell* psCellInChip(
+    const psPlane* coord,              ///< the coordinate in Chip plane
+    const psChip* chip                 ///< the chip to search for the cell
+);
+
+/** Translate a cell coordinate into a chip coordinate
+ *
+ *  @return psPlane*    the resulting chip coordinate
+ */
+psPlane* psCoordCellToChip(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within Cell
+    const psCell* cell                 ///< the Cell in interest
+);
+
+/** Translate a chip coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* psCoordChipToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within Chip
+    const psChip* chip                 ///< the chip in interest
+);
+
+/** Translate a FPA coordinate into a Tangent Plane coordinate
+ *
+ *  @return psPlane*    the resulting Tangent Plane coordinate
+ */
+psPlane* psCoordFPAToTP(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within FPA
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const psFPA* fpa                   ///< the FPA in interest
+);
+
+/** Translate a Tangent Plane coordinate into a Sky coordinate
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* psCoordTPToSky(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within Tangent Plane
+    const psGrommit* grommit           ///< the grommit of the tangent plane
+);
+
+/** Translate a cell coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* psCoordCellToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    const psCell* cell                 ///< the cell in interest
+);
+
+/** Translate a cell coordinate into a Sky coordinate
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* psCoordCellToSky(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const psCell* cell                 ///< the cell in interest
+);
+
+/** Translate a cell coordinate into a Sky coordinate using a 'quick and
+ *  dirty' method
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* psCoordCellToSkyQuick(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    const psCell* cell                 ///< the cell in interest
+);
+
+/** Translate a Sky coordinate into a Tangent Plane coordinate
+ *
+ *  @return psPlane*    the resulting Tangent Plane coordinate
+ */
+psPlane* psCoordSkyToTP(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the sky coordinate
+    const psGrommit* grommit           ///< the grommit
+);
+
+/** Translate a Tangent Plane coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* psCoordTPToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within tangent plane
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const psFPA* fpa                   ///< the FPA of interest
+);
+
+/** Translate a FPA coordinate into a chip coordinate
+ *
+ *  @return psPlane*    the resulting chip coordinate
+ */
+psPlane* psCoordFPAToChip(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the FPA coordinate
+    const psChip* chip                 ///< the chip of interest
+);
+
+/** Translate a chip coordinate into a cell coordinate
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* psCoordChipToCell(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the Chip coordinate
+    const psCell* cell                 ///< the cell of interest
+);
+
+/** Translate a sky coordinate into a cell coordinate
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* psCoordSkyToCell(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the Sky coordinate
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const psCell* cell                 ///< the cell of interest
+);
+
+/** Translate a sky coordinate into a cell coordinate using a 'quick and
+ *  dirty' method
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* psCoordSkyToCellQuick(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the Sky coordinate
+    const psCell* cell                 ///< the cell of interest
+);
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/psCoord.c
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psCoord.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psCoord.c	(revision 1553)
@@ -0,0 +1,453 @@
+/** @file  psCoord.c
+*
+*  @brief Contains basic coordinate transformation definitions and operations
+*
+*  This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup CoordinateTransform
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-13 23:43:29 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psCoord.h"
+#include "psMemory.h"
+#include "psAbort.h"
+#include "psTime.h"
+#include <math.h>
+#include <float.h>
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static float p_psCot(float x);
+static float p_psArg(float x, float y);
+
+/******************************************************************************
+XXX: Do this with a macro.
+ *****************************************************************************/
+float p_psCot(float x)
+{
+    return (1.0 / atan(x));
+}
+
+/******************************************************************************
+XXX: Verify this arc tan function.
+ *****************************************************************************/
+float p_psArg(float x,
+              float y)
+{
+    if (x > 0) {
+        return (atan(y / x));
+    } else if ((x == 0) && (y == 0)) {
+        return (0.5 * M_PI);
+    } else if ((x == 0) && (y == 0)) {
+        return (-0.5 * M_PI);
+    } else if ((x == 0) && (y == 0)) {
+        return (M_PI + atan(y / x));
+    } else if ((x == 0) && (y == 0)) {
+        return (-M_PI + atan(y / x));
+    }
+
+    psAbort(__func__, "Unacceptable range for (p_psArg(%f, %f).\n", x, y);
+    return (0.0);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+psPlane* psPlaneTransformApply(psPlane* out,
+                               const psPlaneTransform* transform,
+                               const psPlane* coords)
+{
+    if (out == NULL) {
+        out = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+    out->x = transform->x->coeff[0][0] +
+             (transform->x->coeff[1][0] * coords->x) +
+             (transform->x->coeff[0][1] * coords->y);
+
+    out->y = transform->y->coeff[0][0] +
+             (transform->y->coeff[1][0] * coords->x) +
+             (transform->y->coeff[0][1] * coords->y);
+
+    return (out);
+}
+
+/******************************************************************************
+This transformation takes into account parameters beyond an objects spatial
+coordinates: term3 and term4 (magnitude and color).
+ *****************************************************************************/
+psPlane* psPlaneDistortApply(psPlane* out,
+                             const psPlaneDistort* transform,
+                             const psPlane* coords,
+                             float color,
+                             float magnitude)
+{
+    if (out == NULL) {
+        out = (psPlane* ) psAlloc(sizeof(psPlane));
+    }
+
+    out->x = transform->x->coeff[0][0][0][0] +
+             (transform->x->coeff[1][0][0][0] * coords->x) +
+             (transform->x->coeff[0][1][0][0] * coords->y) +
+             (transform->x->coeff[0][0][1][0] * color) +
+             (transform->x->coeff[0][0][0][1] * magnitude);
+
+    out->y = transform->y->coeff[0][0][0][0] +
+             (transform->y->coeff[1][0][0][0] * coords->x) +
+             (transform->y->coeff[0][1][0][0] * coords->y) +
+             (transform->y->coeff[0][0][1][0] * color) +
+             (transform->y->coeff[0][0][0][1] * magnitude);
+
+    return (out);
+}
+
+/******************************************************************************
+This function prototype has been modified since the SDRS.
+ *****************************************************************************/
+psSphereTransform* psSphereTransformAlloc(double NPlat,
+        double Xo,
+        double xo)
+{
+    psSphereTransform* tmp = (psSphereTransform* ) psAlloc(sizeof(psSphereTransform));
+
+    tmp->sinPhi = sin(NPlat);
+    tmp->cosPhi = cos(NPlat);
+    tmp->Xo = Xo;
+    tmp->xo = xo;
+
+    return (tmp);
+}
+
+/******************************************************************************
+This algorithm comes from an email from Gene.  I assume (x,y) corresponds to
+(r,d) in the sphere coordinates.
+ 
+XXX: In Gene's email, there are different variables with similar names (y
+and Y) and in the code, there's cos_y, cos_Y, and cos(y).  Verify that there
+are no typo's.
+ *****************************************************************************/
+psSphere* psSphereTransformApply(psSphere* out,
+                                 const psSphereTransform* transform,
+                                 const psSphere* coord)
+{
+    double sinY = 0.0;
+    double cosY = 0.0;
+    double sinX = 0.0;
+    double cosX = 0.0;
+    double x = 0.0;
+    double y = 0.0;
+    double dx = 0.0;
+
+    if (out == NULL) {
+        out = (psSphere* ) psAlloc(sizeof(psSphere));
+    }
+
+    x = coord->r;
+    y = coord->d;
+    dx = x - transform->xo;
+    sinY = cos(y) * sin(dx) * transform->sinPhi + sin(y) * transform->cosPhi;
+    cosY = sqrt(1.0 - sinY * sinY);
+    sinX = (cos(y) * sin(dx) * transform->cosPhi - sin(y) * transform->sinPhi) / cos(y);
+    cosX = cos(y) * cos(dx) / cos(y);
+
+    out->r = atan2(sinX, cosX) + transform->Xo;
+    out->d = atan2(sinY, cosY);
+
+    return (out);
+}
+
+psSphereTransform* psSphereTransformICRStoEcliptic(psTime time)
+{
+    struct tm *tmTime = psTimeToTM(time);
+    double year = (double)(1900 + tmTime->tm_year);
+    double T = year / 100.0;
+    double phi = -23.452294 + 0.013013 * T + 0.000001639 * T * T - 0.000000503 * T * T * T;
+    double Xo = 0.0;
+    double xo = 0.0;
+
+    return (psSphereTransformAlloc(phi, Xo, xo));
+}
+
+psSphereTransform* psSphereTransformEcliptictoICRS(psTime time)
+{
+    struct tm *tmTime = psTimeToTM(time);
+    double year = (double)(1900 + tmTime->tm_year);
+    double T = year / 100.0;
+    double phi = +23.452294 - 0.013013 * T - 0.000001639 * T * T + 0.000000503 * T * T * T;
+    double Xo = 0.0;
+    double xo = 0.0;
+
+    return (psSphereTransformAlloc(phi, Xo, xo));
+}
+
+psSphereTransform* psSphereTransformICRStoGalatic(void)
+{
+    return (psSphereTransformAlloc(62.6, 282.25, 33.0));
+}
+
+psSphereTransform* psSphereTransformGalatictoICRS(void)
+{
+    return (psSphereTransformAlloc(-62.6, 33.0, 282.25));
+}
+
+/******************************************************************************
+XXX: Waiting for the definition of the PS_PROJ_PAR projection.
+XXX: Waiting for the definition of the PS_PROJ_GLS projection.
+ *****************************************************************************/
+psPlane* psProject(const psSphere* coord,
+                   const psProjection* projection)
+{
+    float R = 0.0;
+    float alpha = 0.0;
+    psPlane* tmp = (psPlane* ) psAlloc(sizeof(psPlane));
+
+    if (projection->type == PS_PROJ_TAN) {
+        R = p_psCot(coord->r) * (180.0 / M_PI);
+        tmp->x = R * sin(coord->d);
+        tmp->y = R * cos(coord->d);
+
+    } else if (projection->type == PS_PROJ_SIN) {
+        R = cos(coord->r) * (180.0 / M_PI);
+        tmp->x = R * sin(coord->d);
+        tmp->y = R * cos(coord->d);
+
+    } else if (projection->type == PS_PROJ_CAR) {
+        tmp->x = coord->d;
+        tmp->y = coord->r;
+
+    } else if (projection->type == PS_PROJ_MER) {
+        tmp->x = coord->d;
+        tmp->y = log(tan(45.0 + (0.5 * coord->r))) * 180.0 / M_PI;
+
+    } else if (projection->type == PS_PROJ_AIT) {
+        alpha = 1.0 / ((180.0 / M_PI) * sqrt(1.0 + (cos(coord->r) * cos(0.5 * coord->d) * 0.5)));
+
+        tmp->x = 2.0 * alpha * cos(coord->r) * sin(0.5 * coord->d);
+        tmp->y = alpha * sin(coord->d);
+
+    } else if (projection->type == PS_PROJ_PAR) {
+        psAbort(__func__, "The projection type PS_PROJ_PAR is undefined.\n");
+
+    } else if (projection->type == PS_PROJ_GLS) {
+        psAbort(__func__, "The projection type PS_PROJ_GLS is undefined.\n");
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+XXX: Waiting for the definition of the PS_PROJ_PAR projection.
+XXX: Waiting for the definition of the PS_PROJ_GLS projection.
+ *****************************************************************************/
+psSphere* psDeproject(const psPlane* coord,
+                      const psProjection* projection)
+{
+    float R = 0.0;
+    float chu = 0.0;
+    float chu1 = 0.0;
+    float chu2 = 0.0;
+    psSphere* tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+
+    if (projection->type == PS_PROJ_TAN) {
+        R = sqrt((coord->x * coord->x) + (coord->y * coord->y));
+        tmp->d = p_psArg(-coord->y, coord->x);
+        tmp->r = atan(180.0 / (R * M_PI));
+
+    } else if (projection->type == PS_PROJ_SIN) {
+        R = sqrt((coord->x * coord->x) + (coord->y * coord->y));
+        tmp->d = p_psArg(-coord->y, coord->x);
+        tmp->r = acos((R * M_PI) / 180.0);
+
+    } else if (projection->type == PS_PROJ_CAR) {
+        tmp->d = coord->x;
+        tmp->r = coord->y;
+
+    } else if (projection->type == PS_PROJ_MER) {
+        tmp->d = coord->x;
+        tmp->r = (2.0 * atan(exp((coord->y * M_PI / 180.0)))) - 180.0;
+
+    } else if (projection->type == PS_PROJ_AIT) {
+        chu1 = (coord->x * M_PI) / 720.0;
+        chu1 *= chu1;
+        chu2 = (coord->y * M_PI) / 360.0;
+        chu2 *= chu2;
+        chu = sqrt(1.0 - chu1 - chu2);
+        tmp->d = 2.0 * p_psArg((2.0 * chu * chu) - 1.0, (coord->x * chu * M_PI) / 360.0);
+        tmp->r = asin((coord->y * chu * M_PI) / 180.0);
+
+    } else if (projection->type == PS_PROJ_PAR) {
+        psAbort(__func__, "The projection type PS_PROJ_PAR is undefined.\n");
+
+    } else if (projection->type == PS_PROJ_GLS) {
+        psAbort(__func__, "The projection type PS_PROJ_GLG is undefined.\n");
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+The basic idea is to project both positions onto the linear plane, with
+position1 at the center, then calculate the linear offset between those
+projections.
+ 
+XXX: Do I need to check for unacceptable transformation parameters?  Maybe,
+     if the points are on the North/South Pole, etc?
+ 
+XXX: Do I need to somehow scale this projection?
+ *****************************************************************************/
+psSphere* psSphereGetOffset(const psSphere* restrict position1,
+                            const psSphere* restrict position2,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    psPlane* lin;
+    psProjection proj;
+    psSphere* tmp;
+    double tmpR = 0.0;
+    double tmpD = 0.0;
+
+    if (mode == PS_LINEAR) {
+        proj.R = position1->r;
+        proj.D = position1->d;
+        proj.Xs = 1.0;
+        proj.Ys = 1.0;
+        proj.type = PS_PROJ_TAN;
+
+        lin = psProject(position2, &proj);
+        tmp = psDeproject(lin, &proj);
+        psFree(lin);
+
+        // XXX: Do we need to convert units in tmp?
+        return (tmp);
+    } else if (mode == PS_SPHERICAL) {
+        tmpR = position2->r - position1->r;
+        tmpD = position2->d - position1->d;
+
+        if (unit == PS_ARCSEC) {
+            tmpR = (tmpR * 180.0 * 60.0 * 60.0) / M_PI;
+            tmpD = (tmpR * 180.0 * 60.0 * 60.0) / M_PI;
+        } else if (unit == PS_ARCMIN) {
+            tmpR = (tmpR * 180.0 * 60.0) / M_PI;
+            tmpD = (tmpR * 180.0 * 60.0) / M_PI;
+        } else if (unit == PS_DEGREE) {
+            tmpR = (tmpR * 180.0) / M_PI;
+            tmpD = (tmpR * 180.0) / M_PI;
+        } else if (unit == PS_RADIAN) {}
+        else {
+            psAbort(__func__, "Unknown offset unit: 0x%x\n", unit);
+        }
+
+        tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+        // XXX: Wrap these to an acceptable range.  Is this correct?
+        tmp->r = fmod(tmpR, 2*M_PI);
+        tmp->d = fmod(tmpD, 2*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        return (tmp);
+    }
+    psAbort(__func__, "Unrecognized offset mode\n");
+    return (NULL);
+}
+
+/******************************************************************************
+XXX: Do we need to check for unacceptable transformation parameters?  Maybe,
+     if the points are on the North/South Pole, etc?
+ 
+XXX: Do we need to somehow scale this projection?
+ 
+XXX: I copied the algorithm from the ADD exactly.
+ *****************************************************************************/
+
+psSphere* psSphereSetOffset(const psSphere* restrict position,
+                            const psSphere* restrict offset,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    psPlane lin;
+    psSphere* tmp;
+    psProjection proj;
+    double tmpR = 0.0;
+    double tmpD = 0.0;
+
+    if (mode == PS_LINEAR) {
+        proj.R = position->r;
+        proj.D = position->d;
+        proj.Xs = 1.0;
+        proj.Ys = 1.0;
+        proj.type = PS_PROJ_TAN;
+
+        lin.x = offset->r;
+        lin.y = offset->d;
+
+        tmp = psDeproject(&lin, &proj);
+        return (tmp);
+
+    } else if (mode == PS_SPHERICAL) {
+        if (unit == PS_ARCSEC) {
+            tmpR = (M_PI * offset->r) / (180.0 * 60.0 * 60.0);
+            tmpD = (M_PI * offset->d) / (180.0 * 60.0 * 60.0);
+        } else if (unit == PS_ARCMIN) {
+            tmpR = (M_PI * offset->r) / (180.0 * 60.0);
+            tmpD = (M_PI * offset->d) / (180.0 * 60.0);
+        } else if (unit == PS_DEGREE) {
+            tmpR = (M_PI * offset->r) / (180.0);
+            tmpD = (M_PI * offset->d) / (180.0);
+        } else if (unit == PS_RADIAN) {
+            tmpR = offset->r;
+            tmpD = offset->d;
+        } else {
+            psAbort(__func__, "Unknown offset unit: 0x%x\n", unit);
+        }
+
+        tmp = (psSphere* ) psAlloc(sizeof(psSphere));
+        // XXX: Is this an acceptable way to wrap the angular output?
+        tmp->r = position->r + tmpR;
+        tmp->r = fmod(tmp->r, 2.0*M_PI);
+        tmp->d = position->d + tmpD;
+        tmp->d = fmod(tmp->d, 2.0*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        return (tmp);
+    }
+    psAbort(__func__, "Unrecognized offset mode\n");
+    return (NULL);
+}
Index: /tags/rel2_1/psLib/src/astronomy/psCoord.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psCoord.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psCoord.h	(revision 1553)
@@ -0,0 +1,298 @@
+
+/** @file  psCoord.h
+*
+*  @brief Contains basic coordinate transformation definitions and operations
+*
+*  This file defines the basic types for astronomical coordinate 
+*  transformation
+*
+*  @ingroup CoordinateTransform
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 01:23:20 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_COORD_H
+#define PS_COORD_H
+
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psFunctions.h"
+#include "psTime.h"
+
+/// @addtogroup CoordinateTransform
+/// @{
+
+/** Euclidiean Coordinate System.
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One
+ *  coordinate system to be used is linear coordinates which conform to 
+ *  Euclidean geometry. 
+ *
+ */
+typedef struct
+{
+    double x;                   ///< x position
+    double y;                   ///< y position
+    double xErr;                ///< Error in x position
+    double yErr;                ///< Error in y position
+}
+psPlane;
+
+/** Angular Coordinate System
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One 
+ *  coordinate system to be used is angular coordinates for which additional 
+ *  care must often be taken in comparison to a euclidiean coordinate system.
+ *
+ */
+typedef struct
+{
+    double r;                   ///< RA
+    double d;                   ///< Dec
+    double rErr;                ///< Error in RA
+    double dErr;                ///< Error in Dec
+}
+psSphere;
+
+/** 2D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists simply of two 2D 
+ *  polynomials to transform both components - the output coordinates depend 
+ *  only on the input coordinates and no other quantities of objects at those
+ *  coordinates. 
+ *
+ */
+typedef struct
+{
+    psDPolynomial2D* x;         ///< 2D polynomial transform of X coordinates
+    psDPolynomial2D* y;         ///< 2D polynomial transform of Y coordinates
+}
+psPlaneTransform;
+
+/** 4D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists of two 4D polynomials
+ *  in which the output coordinates are also specified to be a function of the 
+ *  magnitude and color of the object with the given coordinates. This type of 
+ *  coordinate transformation is necessary to represent the (color-dependent) 
+ *  optical distortions caused by the atmosphere and camera optics, and the 
+ *  possibly effects of charge transfer inefficiency.
+ *
+ *  The lowest two terms are the x and y axis of the target system.  The higher
+ *  two terms may represent magnitude and color terms.
+ */
+typedef struct
+{
+    psDPolynomial4D* x;         ///< 4D polynomial transform of X coordinates
+    psDPolynomial4D* y;         ///< 4D polynomial transform of Y coordinates
+}
+psPlaneDistort;
+
+/** Spherical Transform Definition
+ *
+ *  We need to be able to convert between ICRS, Galactic and Ecliptic 
+ *  coordinates, and potentially between arbitrary spherical coordinate 
+ *  systems. All of these basic spherical transformations represent rotations 
+ *  of the spherical coordinate reference. We specify a general 
+ *  transformation function which takes a structure, psSphereTransform, 
+ *  defining the transformation between two spherical coordinate systems 
+ *
+ */
+typedef struct
+{
+    double sinPhi;              ///< sin of North Pole lattitude
+    double cosPhi;              ///< cos of North Pole lattitude
+    double Xo;                  ///< First PT of Ares lon
+    double xo;                  ///< First PT of Ares equiv lon
+}
+psSphereTransform;
+
+/** Projection type for projection/deprojection
+ * 
+ *  @see psProject, psDeproject
+ *
+ */
+typedef enum {
+    PS_PROJ_TAN,                ///< Tangent projection
+    PS_PROJ_SIN,                ///< Sine projection
+    PS_PROJ_AIT,                ///< Aitoff projection
+    PS_PROJ_PAR,                ///< Par projection
+    PS_PROJ_GLS,                ///< GLS projection
+    PS_PROJ_CAR,                ///< CAR projection
+    PS_PROJ_MER,                ///< MER projection
+    PS_PROJ_NTYPE               ///< Number of types; must be last.
+} psProjectionType;
+
+/** Parameter set for projection/deprojection
+ * 
+ *  @see psProject, psDeproject
+ *
+ */
+typedef struct
+{
+    double R;                   ///< Coordinates of projection center
+    double D;                   ///< Coordinates of projection center
+    double Xs;                  ///< plate-scale in X direction
+    double Ys;                  ///< plate-scale in Y direction
+    psProjectionType type;      ///< Projection type
+}
+psProjection;
+
+/** Mode for Offset calculation between two sky positions
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_SPHERICAL,               ///< offset corresponds to an angular offset
+    PS_LINEAR                   ///< offset corresponds to a linear offset
+} psSphereOffsetMode;
+
+/** The units of the offset
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_ARCSEC,                  ///< Arcseconds
+    PS_ARCMIN,                  ///< Arcminutes
+    PS_DEGREE,                  ///< Degrees
+    PS_RADIAN                   ///< Radians
+} psSphereOffsetUnit;
+
+/** Applies the psPlaneTransform transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneTransformApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneTransform* transform, ///< the transform to apply
+    const psPlane* coords              ///< the coordinate to apply the transform above.
+);
+
+/** Applies the psPlaneDistort transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneDistortApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneDistort* transform,   ///< the transform to apply
+    const psPlane* coords,             ///< the coordinate to apply the transform above.
+    float term3,                       ///< third term -- maybe magnitude
+    float term4                        ///< forth term -- maybe color
+);
+
+/** Allocator for psSphereTransform
+ *
+ *  @return psSphereTransform*         newly allocated struct
+ */
+psSphereTransform* psSphereTransformAlloc(
+    double NPlat,                      ///< north pole latitude
+    double Xo,                         ///< First PT of Ares lon
+    double xo                          ///< First PT of Ares equiv lon
+);
+
+/** Applies the psSphereTransform transform for a specified coordinate
+ *
+ *  @return psSphere*      resulting coordinate based on transform
+ */
+psSphere* psSphereTransformApply(
+    psSphere* out,                     ///< a psSphere to recycle.  If NULL, a new one is generated.
+    const psSphereTransform* transform,///< the transform to apply
+    const psSphere* coord              ///< the coordinate to apply the transform above.x
+);
+
+/** Creates the appropriate transform for converting from ICRS to Ecliptic
+ *  coordinate systems.
+ *
+ *  @return psSphereTransform*     transform for ICRS->Ecliptic coordinate systems
+ */
+psSphereTransform* psSphereTransformICRStoEcliptic(
+    psTime time                        ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from Ecliptic to ICRS
+ *  coordinate systems.
+ *
+ *  @return psSphereTransform*     transform for Ecliptic->ICRS coordinate systems
+ */
+psSphereTransform* psSphereTransformEcliptictoICRS(
+    psTime time                        ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from ICRS to Galatic
+ *  coordinate systems.
+ *
+ */
+psSphereTransform* psSphereTransformICRStoGalatic(void);
+
+/** Creates the appropriate transform for converting from Galatic to ICRS
+ *  coordinate systems.
+ *
+ */
+psSphereTransform* psSphereTransformGalatictoICRS(void);
+
+/** Projects a spherical coordinate to a linear coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psPlane* psProject(
+    const psSphere* coord,             ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Reverse projection of a linear coordinate to a spherical coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psSphere* psDeproject(
+    const psPlane* coord,              ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Determines the offset (RA,Dec) on the sky between two positions.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be 
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an 
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset 
+ *  corresponds to a linear offset in a local projection. The offset unit may 
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which 
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*    the offset between position1 and position2
+ */
+psSphere* psSphereGetOffset(
+    const psSphere* restrict position1,
+    const psSphere* restrict position2,
+    psSphereOffsetMode mode,
+    psSphereOffsetUnit unit
+);
+
+/** Applies the given offset to a coordinate.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be 
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an 
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset 
+ *  corresponds to a linear offset in a local projection. The offset unit may 
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which 
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*    the given position with the given offset applied.
+ */
+psSphere* psSphereSetOffset(
+    const psSphere* restrict position,
+    const psSphere* restrict offset,
+    psSphereOffsetMode mode,
+    psSphereOffsetUnit unit
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/psMetadata.c
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psMetadata.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psMetadata.c	(revision 1553)
@@ -0,0 +1,761 @@
+
+/** @file  psMetadata.c
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-14 02:55:46 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include<stdio.h>
+#include<stdarg.h>
+#include<string.h>
+
+#include "fitsio.h"
+#include "psType.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psList.h"
+#include "psHash.h"
+#include "psMetadata.h"
+#include "psString.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+#define FITS_ERROR(STRING,PS_ERROR)                  \
+fits_get_errstatus(status, fitsErr);             \
+psError( __func__, STRING, PS_ERROR, fitsErr);   \
+status = 0;                                      \
+return output;
+
+/** Maximum size of a FITS line */
+#define FITS_LINE_SIZE 80
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH 1024
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+static int metadataId = 0;
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static void metadataItemFree(psMetadataItem* metadataItem)
+{
+    psMetadataType type;
+
+    type = metadataItem->type;
+
+    if (metadataItem == NULL) {
+        return;
+    }
+
+    psFree(metadataItem->name);
+    psFree(metadataItem->comment);
+    psFree(metadataItem->items);
+
+    if (type == PS_META_STR ||
+            type == PS_META_IMG ||
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+        psFree(metadataItem->data.V);
+    }
+}
+
+static void metadataFree(psMetadata* metadata)
+{
+    if (metadata == NULL) {
+        return;
+    }
+    psFree(metadata->list);
+    psFree(metadata->table);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+psMetadataItem* psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    // Get the variable list parameters to pass to allocation function
+    va_start(argPtr, comment);
+
+    // Call metadata item allocation
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    return metadataItem;
+}
+
+psMetadataItem* psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment,
+                                     va_list argPtr)
+{
+    psMetadataItem* metadataItem = NULL;
+
+    if (name == NULL) {
+        psError(__func__, "Null value for name not allowed");
+        return NULL;
+    }
+    // Allocate metadata item
+    metadataItem = (psMetadataItem* ) psAlloc(sizeof(psMetadataItem));
+    if (metadataItem == NULL) {
+        psAbort(__func__, "Failed to allocate memory");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
+
+    // Allocate and set metadata item comment
+    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    if (comment == NULL) {
+        // Per SDRS, null isn't allowed, must use "" instead
+        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
+    } else {
+        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
+    }
+
+    // Set metadata item unique id
+    *(int *)(&metadataItem->id) = ++metadataId;
+
+    // Set metadata item type
+    metadataItem->type = type;
+
+    // Set metadata item value
+    switch (type) {
+    case PS_META_ITEM_SET:
+        metadataItem->data.V = NULL;
+        break;
+    case PS_META_BOOL:
+        metadataItem->data.B = (bool)va_arg(argPtr, int);
+        break;
+    case PS_META_S32:
+        metadataItem->data.S32 = va_arg(argPtr, psS32);
+        break;
+    case PS_META_F32:
+        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
+        break;
+    case PS_META_F64:
+        metadataItem->data.F64 = va_arg(argPtr, psF64);
+        break;
+    case PS_META_STR:
+        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, "Invalid psMetadataType: %d", type);
+    }
+
+    // Allocate and set metadata item name
+    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    vsprintf(metadataItem->name, name, argPtr);
+
+    // Allocate metadata items with same name.
+    metadataItem->items = psListAlloc(NULL);
+
+    return metadataItem;
+}
+
+psMetadata* psMetadataAlloc(void)
+{
+    psList* list = NULL;
+    psHash* table = NULL;
+    psMetadata* metadata = NULL;
+
+    // Allocate metadata
+    metadata = (psMetadata* ) psAlloc(sizeof(psMetadata));
+    if (metadata == NULL) {
+        psAbort(__func__, "Failed to allocate metadata");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadata, (psFreeFcn) metadataFree);
+
+    // Allocate metadata's internal containers
+    list = (psList* ) psListAlloc(NULL);
+    if (list == NULL) {
+        psAbort(__func__, "Failed to allocate list");
+    }
+
+    table = (psHash* ) psHashAlloc(10);
+    if (table == NULL) {
+        psAbort(__func__, "Failed to allocate table");
+    }
+
+    metadata->list = list;
+    metadata->table = table;
+
+    return metadata;
+}
+
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
+    psHash *mdTable = NULL;
+    psList *mdList = NULL;
+    psMetadataItem *existingEntry = NULL;
+    psMetadataItem *newFolderEntry = NULL;
+    psMetadataType newType = PS_META_ITEM_SET;
+
+    if(md == NULL) {
+        psError( __func__, "Null metadata collection not allowed" );
+        return false;
+    }
+
+    if(metadataItem == NULL) {
+        psError( __func__, "Null metadata item not allowed" );
+        return false;
+    }
+
+    newType = metadataItem->type;
+
+    mdTable = md->table;
+    if(mdTable == NULL) {
+        psError( __func__, "Null metadata table not allowed" );
+        return false;
+    }
+
+    mdList = md->list;
+    if(mdList == NULL) {
+        psError( __func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    key = metadataItem->name;
+    if(key == NULL) {
+        psError(__func__, "Null key item not allowed");
+        return false;
+    }
+
+    // See if key is already in table
+    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+    if(existingEntry != NULL) {
+
+        if(existingEntry->type == PS_META_ITEM_SET) {
+
+            // Add leaf node to existing folder node
+            if(!psListAdd(existingEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                         metadataItem->name );
+                return false;
+            }
+        } else if(existingEntry->type != PS_META_ITEM_SET && newType!= PS_META_ITEM_SET) {
+
+            // Leaf node replaces another leaf. Make new folder node and add leaves.
+            newFolderEntry = psMetadataItemAlloc(key, PS_META_ITEM_SET, NULL, NULL);
+
+            if(!psListAdd(newFolderEntry->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psListAdd(newFolderEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, newFolderEntry)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            // Remove local reference to new folder node
+            psMemDecrRefCounter(newFolderEntry);
+        } else {
+
+            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
+            if(!psListAdd(metadataItem->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, metadataItem)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                return false;
+            }
+        }
+    } else {
+
+        // Node doesn't exist - Add new metadata item to metadata collection's hash
+        if(!psHashAdd(mdTable, key, metadataItem)) {
+            psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+            return false;
+        }
+    }
+
+    // Add all items to metadata collection's list, even if they have the same metadata item names
+    if(!psListAdd( mdList, metadataItem, where )) {
+        psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                 metadataItem->name );
+        return false;
+    }
+
+    return true;
+}
+
+bool psMetadataAdd(psMetadata* restrict md, int where, const char *name, psMetadataType type,
+                   const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    va_start(argPtr, comment);
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+    va_end(argPtr);
+
+    if (!psMetadataAddItem(md, where, metadataItem)) {
+        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                metadataItem->name);
+        psFree(metadataItem);
+        return false;
+    }
+    // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
+    // here
+    psMemDecrRefCounter(metadataItem);
+
+    return true;
+}
+
+
+
+bool psMetadataRemove(psMetadata* restrict md, int where, const char *restrict key)
+{
+    int numChildren = 0;
+    psList* mdList = NULL;
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+    psMetadataItem* entryChild = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return false;
+    }
+    // Select removal by key or index
+    if (key != NULL) {
+
+        // Remove by key name
+        entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item. Name: %s", key);
+            return false;
+        }
+
+        numChildren = entry->items->size;
+        if (entry->type == PS_META_ITEM_SET && numChildren > 0) {
+
+            // Table entry has children. Entry and children must be removed from metadata collection's list
+            psListSetIterator(entry->items, PS_LIST_HEAD);
+            entryChild = psListGetCurrent(entry->items);
+            while (entryChild != NULL) {
+                if (!psListRemove(mdList, entryChild, PS_LIST_UNKNOWN)) {
+                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                    return false;
+                }
+                entryChild = psListGetNext(entry->items);
+            }
+        } else {
+
+            // Table entry has no children. Remove entry from metadata collection's list
+            if (!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
+                psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                return false;
+            }
+        }
+        // Remove entry from metadata collection's table
+        if (!psHashRemove(mdTable, key)) {
+            psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
+            return false;
+        }
+    } else {
+
+        // Remove by index
+        entry = psListGet(mdList, where);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item in list. Index: %d", where);
+            return false;
+        }
+
+        key = entry->name;
+        if (key == NULL) {
+            psError(__func__, "Null key name not allowed. Index: %d", where);
+            return false;
+        }
+        // Use recursive remove, now that key is known
+        psMetadataRemove(md, PS_LIST_UNKNOWN, key);
+    }
+
+    return true;
+}
+
+psMetadataItem* psMetadataLookup(psMetadata* restrict md, const char *restrict key)
+{
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return NULL;
+    }
+
+    if (key == NULL) {
+        psError(__func__, "Null key name not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+    if (entry == NULL) {
+        psError(__func__, "Could not find metadata item. Key: %s", key);
+        return NULL;
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGet(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psListGet(mdList, where);
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item with given index. Index: %d", where);
+        return NULL;
+    }
+
+    return entry;
+}
+
+bool psMetadataSetIterator(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    psListSetIterator(mdList, where);
+
+    return true;
+}
+
+psMetadataItem* psMetadataGetNext(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetNext(mdList);
+        } else {
+            return psListGetNext(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item");
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGetPrevious(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetPrevious(mdList);
+        } else {
+            return psListGetPrevious(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item", match);
+    }
+
+    return entry;
+}
+
+void psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* restrict metadataItem)
+{
+    psMetadataType type;
+
+    if (fd == NULL) {
+        psError(__func__, "Null file descriptor not allowed");
+        return;
+    }
+
+    if (format == NULL) {
+        psError(__func__, "Null format not allowed");
+        return;
+    }
+
+    if (metadataItem == NULL) {
+        psError(__func__, "Null metadata not allowed");
+        return;
+    }
+
+    type = metadataItem->type;
+
+    switch (type) {
+    case PS_META_BOOL:
+        fprintf(fd, format, metadataItem->data.B);
+        break;
+    case PS_META_S32:
+        fprintf(fd,format, metadataItem->data.S32);
+        break;
+    case PS_META_F32:
+        fprintf(fd, format, metadataItem->data.F32);
+        break;
+    case PS_META_F64:
+        fprintf(fd, format, metadataItem->data.F64);
+        break;
+    case PS_META_STR:
+        fprintf(fd, format, metadataItem->data.V);
+        break;
+    case PS_META_ITEM_SET:
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, " Invalid psMetadataType to print: %d", type);
+    }
+}
+
+psMetadata* psMetadataFReadHeader(psMetadata* output, char *extName, int extNum, fitsfile * fd)
+{
+    bool tempBool;
+    bool success;
+    char keyType;
+    char keyName[FITS_LINE_SIZE];
+    char keyValue[FITS_LINE_SIZE];
+    char keyComment[FITS_LINE_SIZE];
+    char fitsErr[MAX_STRING_LENGTH];
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    int keyNum = 0;
+    psMetadataType metadataItemType;
+
+    if (fd == NULL) {
+        psError(__func__, "Null FITS file descriptor not allowed");
+        return NULL;
+    }
+
+    if (extName == NULL && extNum == 0) {
+        psError(__func__, "Null extName and extNum = 0 not allowed");
+        return NULL;
+    } else if (extName && extNum) {
+        psError(__func__, "Both extName and extNum arguments should not have non zero values.");
+        return NULL;
+    }
+    // Allocate metadata if user didn't
+    if (output == NULL) {
+        output = psMetadataAlloc();
+    }
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if (extName != NULL) {
+        if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %s: %s", extName);
+        }
+    } else {
+        if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %d: %s", extNum);
+        }
+    }
+
+    // Get number of key names
+    if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
+        FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+    }
+    // Get each key name. Keywords start at one.
+    for (i = 1; i <= numKeys; i++) {
+        if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
+            FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+        }
+        if (fits_get_keytype(keyValue, &keyType, &status) != 0) {
+            fits_get_errstatus(status, fitsErr);
+            if (status != VALUE_UNDEFINED) {
+                FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
+            } else {
+                // Some keywords are still valid even though they don't have a type, like COMMENTS and
+                // HISTORY
+                keyType = 'C';
+                status = 0;
+            }
+        }
+
+        switch (keyType) {
+        case 'I':
+            metadataItemType = PS_META_S32;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atoi(keyValue));
+            break;
+        case 'F':
+            metadataItemType = PS_META_F64;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atof(keyValue));
+            break;
+        case 'C':
+            metadataItemType = PS_META_STR;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, keyValue);
+            break;
+        case 'L':
+            metadataItemType = PS_META_BOOL;
+            tempBool = (keyValue[0] == 'T') ? 1 : 0;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, tempBool);
+            break;
+        case 'U':
+        case 'X':
+        default:
+            psError(__func__, "Invalid psMetadataType: %c", keyType);
+            return output;
+        }
+
+        if (!success) {
+            psError(__func__, "Failed to add metadata item. Name: %s", keyName);
+            return output;
+        }
+    }
+
+    return output;
+}
Index: /tags/rel2_1/psLib/src/astronomy/psMetadata.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psMetadata.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psMetadata.h	(revision 1553)
@@ -0,0 +1,298 @@
+
+/** @file  psMetadata.h
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 01:23:20 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#ifndef PS_METADATA_H
+#define PS_METADATA_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <fitsio.h>
+
+#include "psHash.h"
+#include "psList.h"
+
+/// @addtogroup Metadata
+/// @{
+
+/** Metadata item type.
+ *
+ * Enumeration for maintaining metadata item types.
+ */
+typedef enum {
+    PS_META_ITEM_SET = 0,              ///< Null. Metadata is in psMetadataItem.items
+    PS_META_BOOL,                      ///< Boolean data.
+    PS_META_S32,                       ///< Signed 32-bit integer data.
+    PS_META_F32,                       ///< Single-precision float data.
+    PS_META_F64,                       ///< Double-precision float data.
+    PS_META_STR,                       ///< String data (Stored in as void *).
+    PS_META_IMG,                       ///< Image data (Stored in as void *).
+    PS_META_JPEG,                      ///< JPEG data (Stored in as void *).
+    PS_META_PNG,                       ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                   ///< Other data (Stored in as void *).
+    PS_META_NTYPE                      ///< Number of types. Must be last.
+} psMetadataType;
+
+/** Metadata item data structure.
+ *
+ * Struct for maintaining metadata items of varying types. It also contains
+ * information about the item name, flags, comments, and other items with the same name.
+ */
+typedef struct psMetadataItem
+{
+    const int id;                      ///< Unique ID for metadata item.
+    char *restrict name;               ///< Name of metadata item.
+    psMetadataType type;               ///< Type of metadata item.
+    union {
+        bool B;                        ///< boolean data
+        psS32 S32;                     ///< Signed 32-bit integer data.
+        psF32 F32;                     ///< Single-precision float data.
+        psF64 F64;                     ///< Double-precision float data.
+        psPTR V;                       ///< Pointer to other type of data.
+    } data;                            ///< Union for data types.
+    char *comment;                     ///< Optional comment ("", not NULL).
+    psList* restrict items;            ///< List of psMetadataItems with same name.
+}
+psMetadataItem;
+
+/** Metadata data structure.
+ *
+ *  Struct for holding metadata items. Metadata items are held in two 
+ *  containers. The first employs a doubly-linked list to preserve the order 
+ *  of the metadata. The second container employs a hash table which
+ *  allows fast lookup when given a metadata keyword.
+ */
+typedef struct psMetadata
+{
+    psList* restrict list;             ///< the metadata in linked-list
+    psHash* restrict table;            ///< the metadata in a hash table
+}
+psMetadata;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Create a metadata item.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and 
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAlloc(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata item with va_list.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocV(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata collection.
+ *
+ *  Returns an empty metadata container with fully allocated internal metadata 
+ *  containers.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataAlloc(void);
+
+/** Add existing metadata item to metadata collection.
+ *
+ *  Add a metadata item that has already been created to the metadata 
+ *  collection.
+ *
+ *  @return bool: True for success, false for failure.
+ */
+bool psMetadataAddItem(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    psMetadataItem* restrict item      ///< Metadata item to be added.
+);
+
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataAdd(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Remove an item from metadata collection.
+ *
+ *  Items may be removed from metadata by specifing a key or location. If the 
+ *  name is null, the where argument is used instead. If name is not null, 
+ *  where is set to PS_LIST_UNKNOWN. If the item is found, it is removed from 
+ *  the metadata and true is returned.  If the key is not unique, then all 
+ *  items corresponding to it are removed.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataRemove(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be removed.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on key name.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is 
+ *  non-unique, the first item is returned. If the item is not found, null is 
+ *  returned.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataLookup(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadata item.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on list index.
+ *
+ *  Items may be found in the metadata by their entry position in the list 
+ *  container.
+ *
+ *  @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGet(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where                          ///< Location to be retrieved.
+);
+
+/** Set or reset metadata iterator.
+ *
+ *  Metadata may be iterated by setting or resetting an iterator to a location 
+ *  in the metadata list.
+ *
+ * @return void: void.
+ */
+bool psMetadataSetIterator(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    int where                          ///< Location of iterator.
+);
+
+/** Get next metadata item.
+ *
+ * Get next metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetNext(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Get previous metadata item.
+ *
+ * Get previous metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetPrevious(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Print metadata item to file.
+ *
+ *  Metadata items may be printed to an open file descriptor based on a 
+ *  provided format. The format is a sprintf format statement with exactly 
+ *  one % formatting command. If the metadata item type is a numeric type, 
+ *  this formatting command must also be numeric, and the type conversion 
+ *  performed to the value to match the format type. If the metadata type is 
+ *  a string, the fromatting command must also be for a string. If the
+ *  metadata type is any other data type, printing is not allowed.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+void psMetadataItemPrint(
+    FILE * fd,                         ///< Pointer to file to write metadata item.
+    const char *format,                ///< Format to print metadata item.
+    const psMetadataItem* restrict metadataItem ///< Metadata item to print.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported. This file is currently unimplemented.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extname,                     ///< File name extension string.
+    int extnum,                        ///< File name extension number. Starts at 1.
+    char *filename                     ///< Name of file to read.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataFReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extName,                     ///< File name extension string.
+    int extNum,                        ///< File name extension number.
+    fitsfile * fd                      ///< Pointer to file to read.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/psPhotometry.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psPhotometry.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psPhotometry.h	(revision 1553)
@@ -0,0 +1,75 @@
+
+/** @file  psPhotometry.h
+*
+*  @brief Contains basic photometric structures.
+*
+*  This file defines the basic photometric structures.
+*
+*  @ingroup Photometry
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:40:54 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_PHOTOMETRIC_H
+#define PS_PHOTOMETRIC_H
+
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psFunctions.h"
+
+/// @addtogroup Photometry
+/// @{
+
+/** The photometric system description
+ *
+ *  The photometric system is defined by the psPhotSystem structure. A 
+ *  photometric system is identified by a human-readable name (ie, SDSS.g, 
+ *  Landolt92.B, GPC1.OTA32.r). Each photometric system is given a unique 
+ *  identifier ID. Observations taken with a specific camera, detector, and 
+ *  filter represent their own photometric system, and it may be necessary to 
+ *  perform transformations between these systems. Photometric systems 
+ *  associated with observations from a specific camera/ detector/filter 
+ *  combination can be associated with those components.
+ *
+ */
+
+typedef struct
+{
+    const int ID;               ///< ID number for this photometric system
+    const char *name;           ///< Name of photometric system
+    const char *camera;         ///< Camera for photometric system
+    const char *filter;         ///< Filter used for photometric system
+    const char *detector;       ///< Detector used for photometric system
+}
+psPhotSystem;
+
+/** Photometric system transformation
+ *
+ *  This structure defines the transformation between two photometric systems.
+ *
+ */
+
+typedef struct
+{
+    psPhotSystem src;           ///< Source photometric system
+    psPhotSystem dst;           ///< Destination photometric system
+    psPhotSystem pP;            ///< Primary color reference
+    psPhotSystem pM;            ///< Primary color reference
+    psPhotSystem sP;            ///< Secondary color reference
+    psPhotSystem sM;            ///< Secondary color reference
+    float pA;                   ///< Color offset for references
+    float sA;                   ///< Color offset for references
+    psPolynomial3D transform;   ///< Transformation from source to destination
+}
+psPhotTransform;
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/psTime.c
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psTime.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psTime.c	(revision 1553)
@@ -0,0 +1,549 @@
+
+/** @file  psTime.c
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy
+ *  functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
+ *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
+ *  base upon which International Atomic Time (TAI) time is calculated. TAI time varies over time due to the
+ *  earth's rotation and the movement of the continental plates. It is currentls 32 seconds faster than
+ *  UTC/timeval time.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-13 23:47:10 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psTime.h"
+#include "psError.h"
+#include "psMemory.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+/** Number of available leapsecond updates */
+#define NUM_LEAPSECOND_UPDATES 23
+
+/** Maximum length of time string */
+#define MAX_TIME_STRING_LENGTH 256
+
+/** Seconds per minute */
+#define  SEC_PER_MINUTE 60.0
+
+/** Seconds per hour */
+#define  SEC_PER_HOUR (60.0*SEC_PER_MINUTE)
+
+/** Seconds per day */
+#define  SEC_PER_DAY (24.0*SEC_PER_HOUR)
+
+/** Seconds per year */
+#define  SEC_PER_YEAR (365.0*SEC_PER_DAY)
+
+/** Microseconds per day */
+#define USEC_PER_DAY 86400000000.0
+
+/** Preprocessor macro to generate error for negative time in struct */
+#define CHECK_NEGATIVE_TIME_STRUCT(NAME,RETURN)                                                              \
+if(NAME.tv_sec < 0) {                                                                                        \
+    psError(__func__,"Negative seconds are not allowed: %ld", NAME.tv_sec);                                  \
+    return RETURN;                                                                                           \
+} else if(NAME.tv_usec<0) {                                                                                  \
+    psError(__func__,"Negative microseconds are not allowed: %ld", NAME.tv_usec);                            \
+    return RETURN;                                                                                           \
+}
+
+/** Preprocessor macro to generate error for negative time */
+#define CHECK_NEGATIVE_TIME(NAME,RETURN)                                                                     \
+if(NAME < 0.0) {                                                                                             \
+    psError(__func__,"Negative time is not allowed: %f", NAME);                                              \
+    return RETURN;                                                                                           \
+}                                                                                                            \
+
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+/* The table below comes from http://tycho.usno.navy.mil/leapsec.html, which reports the current state of
+the TAI/UTC leapsecond conversion times. This table is placed into a two dimensional array and used by
+the psTimeGetTime() function to calculate TAI time from  UTC time.
+ 
+ 1972 JAN 1 = JD 2441317.5  TAI-UTC = 10.0
+ 1972 JUL 1 = JD 2441499.5  TAI-UTC = 11.0
+ 1973 JAN 1 = JD 2441683.5  TAI-UTC = 12.0
+ 1974 JAN 1 = JD 2442048.5  TAI-UTC = 13.0
+ 1975 JAN 1 = JD 2442413.5  TAI-UTC = 14.0
+ 1976 JAN 1 = JD 2442778.5  TAI-UTC = 15.0
+ 1977 JAN 1 = JD 2443144.5  TAI-UTC = 16.0
+ 1978 JAN 1 = JD 2443509.5  TAI-UTC = 17.0
+ 1979 JAN 1 = JD 2443874.5  TAI-UTC = 18.0
+ 1980 JAN 1 = JD 2444239.5  TAI-UTC = 19.0
+ 1981 JUL 1 = JD 2444786.5  TAI-UTC = 20.0
+ 1982 JUL 1 = JD 2445151.5  TAI-UTC = 21.0
+ 1983 JUL 1 = JD 2445516.5  TAI-UTC = 22.0
+ 1985 JUL 1 = JD 2446247.5  TAI-UTC = 23.0
+ 1988 JAN 1 = JD 2447161.5  TAI-UTC = 24.0
+ 1990 JAN 1 = JD 2447892.5  TAI-UTC = 25.0
+ 1991 JAN 1 = JD 2448257.5  TAI-UTC = 26.0
+ 1992 JUL 1 = JD 2448804.5  TAI-UTC = 27.0
+ 1993 JUL 1 = JD 2449169.5  TAI-UTC = 28.0
+ 1994 JUL 1 = JD 2449534.5  TAI-UTC = 29.0
+ 1996 JAN 1 = JD 2450083.5  TAI-UTC = 30.0
+ 1997 JUL 1 = JD 2450630.5  TAI-UTC = 31.0
+ 1999 JAN 1 = JD 2451179.5  TAI-UTC = 32.0
+*/
+
+// Table for Julian date of leapsecond update and current total number of leapseconds at that date
+static double leapseconds[NUM_LEAPSECOND_UPDATES][2] = {
+            {
+                2441317.5, 10.0},
+            {
+                2441499.5, 11.0},
+            {
+                2441683.5, 12.0},
+            {
+                2442048.5, 13.0},
+            {
+                2442413.5, 14.0},
+            {
+                2442778.5, 15.0},
+            {
+                2443144.5, 16.0},
+            {
+                2443509.5, 17.0},
+            {
+                2443874.5, 18.0},
+            {
+                2444239.5, 19.0},
+            {
+                2444786.5, 20.0},
+            {
+                2445151.5, 21.0},
+            {
+                2445516.5, 22.0},
+            {
+                2446247.5, 23.0},
+            {
+                2447161.5, 24.0},
+            {
+                2447892.5, 25.0},
+            {
+                2448257.5, 26.0},
+            {
+                2448804.5, 27.0},
+            {
+                2449169.5, 28.0},
+            {
+                2449534.5, 29.0},
+            {
+                2450083.5, 30.0},
+            {
+                2450630.5, 31.0},
+            {
+                2451179.5, 32.0}
+        };
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psTime psTimeGetTime(void)
+{
+    struct timeval now;
+    psTime time;
+
+    time.tv_sec = 0;
+    time.tv_usec = 0;
+
+    if (gettimeofday(&now, (struct timezone *)0) == -1) {
+        psError(__func__, " : Line %d - Failed to get time", __LINE__);
+        return time;
+    }
+    // Convert timeval time to psTime
+    time.tv_sec = now.tv_sec;
+    time.tv_usec = now.tv_usec;
+
+    // Add most current leapseconds value to UTC time to get TAI time
+    time.tv_sec += leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+
+    return time;
+}
+
+char *psTimeToISO(psTime time)
+{
+    int ms = 0;
+    char *timeString = NULL;
+    char *tempString = NULL;
+    struct tm *tmTime = NULL;
+    time_t sec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, NULL);
+
+    tempString = psAlloc(MAX_TIME_STRING_LENGTH);
+    timeString = psAlloc(MAX_TIME_STRING_LENGTH);
+
+    // Converts psTime to YYYY/MM/DD,HH:MM:SS.SSS in string form
+    ms = time.tv_usec / 1000;
+
+    sec = time.tv_sec;
+    // tmTime variable is statically allocated, no need to free
+    tmTime = gmtime(&sec);
+    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
+        psError(__func__, " : Line %d - Failed strftime conversion", __LINE__);
+    }
+
+    if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3d", tempString, ms) < 0) {
+        psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
+    }
+    psFree(tempString);
+
+    return timeString;
+}
+
+psTime psTimeToUTC(psTime time)
+{
+    int i = 0;
+    double jd = 0.0;
+    double ls = 0.0;
+    double *jdTable = NULL;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, outTime);
+
+    // Find leapseconds to subtract from psTime to get UTC time
+    jd = psTimeToJD(time);
+    jdTable = leapseconds[0];
+    for (i = 0; i < NUM_LEAPSECOND_UPDATES; i++, jdTable += 2) {
+        if (jd > *jdTable) {
+            ls = *(jdTable + 1);
+        }
+    }
+
+    outTime.tv_sec = time.tv_sec - ls;
+    outTime.tv_usec = time.tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+double psTimeToMJD(psTime time)
+{
+    double mjd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, mjd);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    mjd = time.tv_sec / SEC_PER_DAY + time.tv_usec / USEC_PER_DAY + 40587.0;
+
+    return mjd;
+}
+
+double psTimeToJD(psTime time)
+{
+    double jd = 0.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, jd);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    jd = time.tv_sec / SEC_PER_DAY + time.tv_usec / USEC_PER_DAY + 2440587.5;
+
+    return jd;
+}
+
+struct timeval psTimeToTimeval(psTime time)
+{
+    struct timeval timevalTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, timevalTime);
+    timevalTime.tv_sec = time.tv_sec;
+    timevalTime.tv_usec = time.tv_usec;
+
+    return timevalTime;
+}
+
+struct tm *psTimeToTM(psTime time)
+{
+    struct tm *tmTime = NULL;
+    time_t sec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, tmTime);
+    sec = time.tv_sec;
+    tmTime = gmtime(&sec);
+
+    return tmTime;
+}
+
+psTime psISOToTime(char *time)
+{
+    char tempString[MAX_TIME_STRING_LENGTH];
+    int month;
+    int day;
+    int year;
+    int hour;
+    int minute;
+    int second;
+    int millisecond;
+    struct tm tmTime;
+    psTime outTime;
+
+    strncpy(tempString, time, MAX_TIME_STRING_LENGTH);
+
+    // Convert YYYY/MM/DD,HH:MM:SS.SSS in string form to tm time
+    year = atoi(strtok(tempString, "/"));
+    if (year < 1900) {
+        psError(__func__, "Years less than 1900 not allowed. Value: %d", year);
+        return outTime;
+    }
+
+    month = atoi(strtok(NULL, "/"));
+    if (month < 1 || month > 12) {
+        psError(__func__, "Month must have a value from 1 to 12. Value: %d", month);
+        return outTime;
+    }
+
+    day = atoi(strtok(NULL, ","));
+    if (day < 1 || day > 31) {
+        psError(__func__, "Day must have a value from 1 to 31. Value: %d", day);
+        return outTime;
+    }
+
+    hour = atoi(strtok(NULL, ":"));
+    if (hour < 0 || hour > 23) {
+        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", hour);
+        return outTime;
+    }
+
+    minute = atoi(strtok(NULL, ":"));
+    if (minute < 0 || minute > 59) {
+        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", minute);
+        return outTime;
+    }
+
+    second = atoi(strtok(NULL, "."));
+    if (second < 0 || second > 59) {
+        psError(__func__, "Second must have a value from 0 to 59. Value: %d", second);
+        return outTime;
+    }
+
+    millisecond = atoi(strtok(NULL, "X"));
+    if (millisecond < 0 || millisecond > 1000) {
+        psError(__func__, "Millisecond must have a value from 0 to 999. Value: %d", millisecond);
+        return outTime;
+    }
+
+    tmTime.tm_year = year - 1900;
+    tmTime.tm_mon = month - 1;
+    tmTime.tm_mday = day;
+    tmTime.tm_hour = hour;
+    tmTime.tm_min = minute;
+    tmTime.tm_sec = second;
+    tmTime.tm_isdst = -1;
+
+    // Convert tm time to psTime
+    outTime = psTMToTime(&tmTime);
+    outTime.tv_usec = millisecond * 1000;
+
+    return outTime;
+}
+
+psTime psUTCToTime(psTime time)
+{
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME_STRUCT(time, outTime);
+
+    // Convert UTC time to psTime/TAI
+    outTime.tv_sec = time.tv_sec + leapseconds[NUM_LEAPSECOND_UPDATES - 1][1];
+    outTime.tv_usec = time.tv_usec;
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psMJDToTime(double time)
+{
+    psTime outTime;
+    double days = 0.0;
+    double seconds = 0.0;
+
+    CHECK_NEGATIVE_TIME(time, outTime);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = time - 40587.0;
+
+    // Convert to psTime/TAI
+    seconds = days * SEC_PER_DAY;
+    outTime.tv_usec = (seconds - (long)seconds) * 1000000.0;
+    outTime.tv_sec = seconds;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psJDToTime(double time)
+{
+    double days = 0.0;
+    double seconds = 0.0;
+    psTime outTime;
+
+    CHECK_NEGATIVE_TIME(time, outTime);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = time - 2440587.5;
+
+    // Convert to psTime/TAI
+    seconds = days * SEC_PER_DAY;
+    outTime.tv_sec = seconds;
+    outTime.tv_usec = (seconds - (long)seconds) * 1000000.0;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psTimevalToTime(struct timeval * time)
+{
+    psTime outTime;
+
+    if (time == NULL)
+    {
+        psError(__func__, "Null value for timeval arg not allowed");
+        return outTime;
+    } else if (time->tv_sec < 0)
+    {
+        psError(__func__, "Negative seconds are not allowed: %ld", time->tv_sec);
+        return outTime;
+    } else if (time->tv_usec < 0)
+    {
+        psError(__func__, "Negative microseconds are not allowed: %ld", time->tv_usec);
+        return outTime;
+    }
+    // Convert to psTime/TAI
+    outTime.tv_sec = time->tv_sec;
+    outTime.tv_usec = time->tv_usec;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
+
+psTime psTMToTime(struct tm * time)
+{
+    int i;
+    int n;
+    int y;
+    int mon[] = {
+                    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+                };
+    long epoch;
+    psTime outTime;
+
+    i = 0;
+    n = 0;
+    y = 0;
+    epoch = 0;
+
+    if (time == NULL)
+    {
+        psError(__func__, "Null value for tm arg not allowed");
+        return outTime;
+    } else if (time->tm_year < 70)
+    {
+        psError(__func__, "Input times earlier than 1970 not allowed. Value: %d", time->tm_year + 1900);
+        return outTime;
+    } else if (time->tm_mon < 0 || time->tm_mon > 11)
+    {
+        psError(__func__, "Month must have a value from 0 to 11. Value: %d", time->tm_mon);
+        return outTime;
+    } else if (time->tm_mday < 1 || time->tm_mday > 31)
+    {
+        psError(__func__, "Day must have a value from 1 to 31. Value: %d", time->tm_mday);
+        return outTime;
+    } else if (time->tm_hour < 0 || time->tm_hour > 23)
+    {
+        psError(__func__, "Hour must have a value from 0 to 23. Value: %d", time->tm_hour);
+        return outTime;
+    } else if (time->tm_min < 0 || time->tm_min > 59)
+    {
+        psError(__func__, "Minute must have a value from 0 to 59. Value: %d", time->tm_min);
+        return outTime;
+    } else if (time->tm_sec < 0 || time->tm_sec > 59)
+    {
+        psError(__func__, "Second must have a value from 0 to 59. Value: %d", time->tm_sec);
+        return outTime;
+    }
+
+    n = time->tm_year + 1900 - 1;
+    epoch = (time->tm_year - 70) * SEC_PER_YEAR + ((n / 4 - n / 100 + n / 400) -
+            (1969 / 4 - 1969 / 100 + 1969 / 400)) * SEC_PER_DAY;
+
+    y = time->tm_year + 1900;
+
+    // Adjust for leap years
+    for (i = 0; i < time->tm_mon; i++)
+    {
+        epoch += mon[i] * SEC_PER_DAY;
+        if (i == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
+            epoch += SEC_PER_DAY;
+        }
+    }
+
+    // Add everything
+    epoch += (time->tm_mday - 1) * SEC_PER_DAY;
+    epoch += time->tm_hour * SEC_PER_HOUR + time->tm_min * SEC_PER_MINUTE + time->tm_sec;
+
+    // Create psTime
+    outTime.tv_usec = 0;
+    outTime.tv_sec = epoch;
+
+    CHECK_NEGATIVE_TIME_STRUCT(outTime, outTime);
+
+    return outTime;
+}
Index: /tags/rel2_1/psLib/src/astronomy/psTime.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/psTime.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/psTime.h	(revision 1553)
@@ -0,0 +1,203 @@
+
+/** @file  psTime.h
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy
+ *  functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
+ *  of conversions between specific time formats.  PSLib currently uses the UNIX timeval time system as the
+ *  base upon which International Atomic Time (TAI) time is calculated. All time conversion functions within
+ *  psLib, except those noted, are calculated in terms of TAI time, which is approxinmately 32 seconds faster
+ *  than UTC/timeval.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-13 22:08:51 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSTIME_H
+#define PSTIME_H
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "psType.h"
+
+/// @addtogroup Time
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Definition of psTime.
+ *
+ *  The psTime struct is used by psLib to represent time values critical to 
+ *  astronomical calculations.  This structure represents a time which is 
+ *  equivalent to TAI (International Atomic Time) and is measured in both 
+ *  seconds and microseconds.
+ */
+typedef struct timeval psTime;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Get current TAI time.
+ *
+ * Gets current time from the system clock in correct TAI units.
+ *
+ *  @return  psTime: Struct with current time.
+ */
+
+psTime psTimeGetTime(void);
+
+/** Convert psTime to ISO time in TAI units.
+ *
+ *  Converts psTime to a null terminated string in the form of: 
+ *  YYYY/MM/DD,HH:MM:SS.SSS. This function assumes the input time already is 
+ *  in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  char*: Pointer null terminated array of chars in ISO time.
+ */
+
+char *psTimeToISO(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to UTC time.
+ *
+ *  Converts psTime to UTC time in double precision floating point notation. 
+ *  The input to this must already be int TAI time. The result from this 
+ *  function is not in TAI units, but that of UTC, which does not contain
+ *  leapseconds.
+ *
+ *  @return  psTime: UTC time psTime format.
+ */
+
+psTime psTimeToUTC(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to modified Julian date time.
+ *
+ *  Converts psTime to modified Julian date (MJD) time. This function assumes 
+ *  the input time already is in TAI time and does not add or subtract 
+ *  leapseconds.
+ *
+ *  @return  double: Modified Julian Days (MJD) time.
+ */
+double psTimeToMJD(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to Julian date time.
+ *
+ *  Converts psTime to Julian date (JD) time. This function assumes the input 
+ *  time already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  double: Julian Date (JD) time.
+ */
+double psTimeToJD(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert psTime to timeval time.
+ *
+ *  Converts psTime to timeval time. This function assumes the input time 
+ *  already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  timeval: timeval struct time.
+ */
+struct timeval psTimeToTimeval(
+                psTime time                        ///< Input time to be converted.
+            );
+
+/** Convert psTime to tm time.
+ *
+ * Converts psTime to tm time. This function assumes the input time already is in TAI time and does not add or
+ * subtract leapseconds.
+ *
+ *  @return  tm: tm struct time.
+ */
+struct tm *psTimeToTM(
+                psTime time                        ///< Input time to be converted.
+            );
+
+/** Convert ISO to psTime.
+ *
+ *  Converts ISO time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time
+ */
+psTime psISOToTime(
+    char *time                         ///< Input time to be converted.
+);
+
+/** Convert UTC to psTime.
+ *
+ *  Converts UTC time to psTime. This function assumes the input time already 
+ *  is in TAI time and add or subtracts the necessary leapseconds.
+ *
+ *  @return  psTime: time in TAI units.
+ */
+psTime psUTCToTime(
+    psTime time                        ///< Input time to be converted.
+);
+
+/** Convert MJD to psTime.
+ *
+ *  Converts MJD time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psMJDToTime(
+    double time                        ///< Input time to be converted.
+);
+
+/** Convert JD to psTime.
+ *
+ *  Converts JD time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psJDToTime(
+    double time                        ///< Input time to be converted.
+);
+
+/** Convert timeval to psTime.
+ *
+ *  Converts timeval time to psTime. This function assumes the input time 
+ *  already is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psTimevalToTime(
+    struct timeval *time               ///< Input time to be converted.
+);
+
+/** Convert tm time to psTime.
+ *
+ *  Converts tm time to psTime. This function assumes the input time already 
+ *  is in TAI time and does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime psTMToTime(
+    struct tm *time                    ///< Input time to be converted.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/astronomy/slalib.h
===================================================================
--- /tags/rel2_1/psLib/src/astronomy/slalib.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/astronomy/slalib.h	(revision 1553)
@@ -0,0 +1,119 @@
+/** @file  slalib.h
+*
+*  @brief Simple wrapper of the required fortran SLALIB functions
+*
+*  @ingroup AstroImage
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-13 01:14:26 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef SLALIB_H
+#define SLALIB_H
+
+#ifdef FORTRAN_UNDERSCORE_PREFIX
+#ifdef FORTRAN_DOUBLE_UNDERSCORE_SUFFIX
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa _SLA_AOPPA__
+#define slaAopqk _SLA_AOPQK__
+#define slaOapqk _SLA_OAPQK__
+#else
+#define slaAoppa _sla_aoppa__
+#define slaAopqk _sla_aopqk__
+#define slaOapqk _sla_oapqk__
+#endif
+#elseif FORTRAN_NO_UNDERSCORE_SUFFIX
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa _SLA_AOPPA
+#define slaAopqk _SLA_AOPQK
+#define slaOapqk _SLA_OAPQK
+#else
+#define slaAoppa _sla_aoppa
+#define slaAopqk _sla_aopqk
+#define slaOapqk _sla_oapqk
+#endif
+#else
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa _SLA_AOPPA_
+#define slaAopqk _SLA_AOPQK_
+#define slaOapqk _SLA_OAPQK_
+#else
+#define slaAoppa _sla_aoppa_
+#define slaAopqk _sla_aopqk_
+#define slaOapqk _sla_oapqk_
+#endif
+#endif
+#else
+#ifdef FORTRAN_DOUBLE_UNDERSCORE_SUFFIX
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa SLA_AOPPA__
+#define slaAopqk SLA_AOPQK__
+#define slaOapqk SLA_OAPQK__
+#else
+#define slaAoppa sla_aoppa__
+#define slaAopqk sla_aopqk__
+#define slaOapqk sla_oapqk__
+#endif
+#elseif FORTRAN_NO_UNDERSCORE_SUFFIX
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa SLA_AOPPA
+#define slaAopqk SLA_AOPQK
+#define slaOapqk SLA_OAPQK
+#else
+#define slaAoppa sla_aoppa
+#define slaAopqk sla_aopqk
+#define slaOapqk sla_oapqk
+#endif
+#else
+#ifdef FORTRAN_UPPERCASE
+#define slaAoppa SLA_AOPPA_
+#define slaAopqk SLA_AOPQK_
+#define slaOapqk SLA_OAPQK_
+#else
+#define slaAoppa sla_aoppa_
+#define slaAopqk sla_aopqk_
+#define slaOapqk sla_oapqk_
+#endif
+#endif
+#endif
+extern void slaAoppa (
+        double date,
+        double dut,
+        double elongm,
+        double phim,
+        double him,
+        double xp,
+        double yp,
+        double tdk,
+        double pmb,
+        double rh,
+        double wl,
+        double tlr,
+        double *AOPRMS
+    );
+
+extern void slaAopqk (
+        double RAP,
+        double DAP,
+        double *AOPRMS,
+        double *AOB,
+        double *ZOB,
+        double *HOB,
+        double *DOB,
+        double *ROB
+    );
+
+extern void slaOapqk (
+        char *TYPE,
+        double OB1,
+        double OB2,
+        double *AOPRMS,
+        double *RAP,
+        double *DAP
+    );
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/src/collections/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/.cvsignore	(revision 1553)
@@ -0,0 +1,1 @@
+*.i
Index: /tags/rel2_1/psLib/src/collections/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/collections/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/Makefile	(revision 1553)
@@ -0,0 +1,86 @@
+###############################################################################
+##
+##  Makefile:   collections
+##
+##  $Revision: 1.28 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-09 20:29:43 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+###############################################################################
+
+# Define variable prefix to the top level project - psLib
+# This is necessary for definition is Makefile.Globals uses prefix
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+# Define the two targets to be built
+
+TARGET_STATIC  = libpslib.a
+
+# Include the make global definitions for the project
+
+include ../Makefile.Globals
+
+# Set CFLAGS used by the implicit rule to compile .c
+
+CFLAGS := $(CFLAGS_RELOC) -I../sysUtils 
+
+# Define the source objects
+ 
+SRC_OBJS = psBitSet.o \
+           psVector.o \
+           psList.o \
+           psScalar.o \
+           psCompare.o \
+           psArray.o \
+           psHash.o
+
+OBJS = $(addprefix makedir/,$(SRC_OBJS))
+
+# Define PHONY target "all" which will make all the necessary items
+
+all: $(TARGET_STATIC)
+
+# Rule to make static library
+
+libpslib.a: $(OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs ../$@ $(OBJS)
+
+# Define PHONY target "install" which will install necessary files
+
+install: $(TARGET_STATIC)
+	install *.h $(includedir)
+
+# Define PHONY target "distclean" which will cleanup the distribution
+
+distclean:	clean
+	$(RM) ../$(TARGET_STATIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+
+clean:
+	@echo "    Deleting intermediate files for 'collections'"
+	$(RM) $(OBJS) *.lint $(SRC_OBJS:.o=.i)
+
+cleandep:
+	$(RM) $(OBJS:.o=.d)
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+%.i: %.c
+	$(CC) -E $(CFLAGS) -o $@ $<
+
+makedir/%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+makedir/%.d: %.c
+	$(CC) -MM $(CFLAGS) $< > $@.tmp
+	sed 's|\($*\)\.o[ :]*|\1.o $@ : |g' $@.tmp > $@
+	$(RM) -f $@.tmp
+
+include $(OBJS:.o=.d)
Index: /tags/rel2_1/psLib/src/collections/psArray.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psArray.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psArray.c	(revision 1553)
@@ -0,0 +1,122 @@
+
+/** @file  psArray.c
+ *
+ *  @brief Contains support for basic vector types
+ *
+ *  This file defines the basic type for a vector struct and functions useful
+ *  in manupulating vectors.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include<stdlib.h>                         // for qsort, etc.
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psArray.h"
+#include "psLogMsg.h"
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void arrayFree(psArray* restrict psArr);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psArray* psArrayAlloc(unsigned int nalloc)
+{
+    psArray* psArr = NULL;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);
+        return NULL;
+    }
+    // Create vector struct
+    psArr = (psArray* ) psAlloc(sizeof(psArray));
+    p_psMemSetDeallocator(psArr, (psFreeFcn) arrayFree);
+
+    psArr->nalloc = nalloc;
+    psArr->n = nalloc;
+
+    // Create vector data array
+    psArr->data = psAlloc(nalloc * sizeof(psPTR));
+
+    return psArr;
+}
+
+psArray* psArrayRealloc(unsigned int nalloc, psArray* restrict in)
+{
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for realloc (%d)\n", nalloc);
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "Null input vector\n");
+        return NULL;
+    } else if (in->nalloc != nalloc) {     // No need to realloc to same size
+        if (nalloc < in->n) {
+            for (int i = nalloc; i < in->n; i++) {      // For reduction in vector size
+                psFree(in->data[i]);
+            }
+            in->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        in->data = psRealloc(in->data, nalloc * sizeof(psPTR));
+        in->nalloc = nalloc;
+    }
+
+    return in;
+}
+
+static void arrayFree(psArray* restrict psArr)
+{
+    if (psArr == NULL) {
+        return;
+    }
+
+    psArrayElementFree(psArr);
+
+    psFree(psArr->data);
+}
+
+void psArrayElementFree(psArray* restrict psArr)
+{
+
+    if (psArr == NULL) {
+        return;
+    }
+
+    for (int i = 0; i < psArr->n; i++) {
+        psFree(psArr->data[i]);
+        psArr->data[i] = NULL;
+    }
+}
+
+psArray* psArraySort(psArray* in, psComparePtrFcn compare)
+{
+    if (in == NULL) {
+        return NULL;
+    }
+
+    qsort(in->data, in->n, sizeof(psPTR), (int (*)(const void *, const void *))compare);
+
+    return in;
+}
Index: /tags/rel2_1/psLib/src/collections/psArray.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psArray.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psArray.h	(revision 1553)
@@ -0,0 +1,105 @@
+
+/** @file  psArray.h
+ *
+ *  @brief Contains basic array definitions and operations
+ *
+ *  This file defines the basic type for a array struct and functions useful
+ *  in manupulating arrays.
+ *
+ *  @ingroup Array
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:47:31 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ARRAY_H
+#define PS_ARRAY_H
+
+#include "psType.h"
+#include "psCompare.h"
+
+/// @addtogroup Array
+/// @{
+
+/** An array to support primitive types.
+ *
+ * Struct for maintaining an array of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    unsigned int nalloc;        ///< Total number of elements available.
+    unsigned int n;             ///< Number of elements in use.
+    psPTR* data;                ///< An Array of pointer elements
+}
+psArray;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate an array.
+ *
+ * Uses psLib memory allocation functions to create an array collection of 
+ * data
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+psArray* psArrayAlloc(
+    unsigned int nalloc                ///< Total number of elements to make available.
+);
+
+/** Reallocate an array.
+ *
+ * Uses psLib memory allocation functions to reallocate an array collection 
+ * of data. 
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+psArray* psArrayRealloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psArray* restrict psArr            ///< array to reallocate.
+);
+
+/** Deallocate/Dereference elements of an array.
+ *
+ * Uses psLib memory allocation functions to deallocate/dereference elements 
+ * of a array of void pointers.  The array psArr is not freed, and its elements
+ * will all be set to NULL.
+ *
+ */
+void psArrayElementFree(
+    psArray* restrict psArr            ///< Void pointer array to destroy.
+);
+
+/** Sort the array according to an external compare function.
+ *
+ *  Sorts an array via the specification of a comparison function
+ *  to specify how the objects on the array should be sorted.
+ *
+ *  The comparison function must return an integer less than, equal to, or 
+ *  greater than zero if the first argument is considered to be respectively 
+ *  less than, equal to, or greater than the second. 
+ *
+ *  If two members compare as equal, their order in the sorted array is 
+ *  undefined.
+ *
+ *  @return psArray* The sorted array.
+ */
+psArray* psArraySort(
+    psArray* in,                       ///< input array to sort.
+    psComparePtrFcn compare            ///< the compare function
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psBitSet.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psBitSet.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psBitSet.c	(revision 1553)
@@ -0,0 +1,297 @@
+
+/** @file  psBitSet.c
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdbool.h>
+
+#include "psBitSet.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void psBitSetFree(psBitSet* restrict inBitSet);
+
+/** Private function to create a mask.
+ *
+ *  Creates an eight bit mask with the given bit set. All other bits in the byte are zero. The input bit uses
+ *  zero-based indexing, and is the cumulitive index within the array, not the localized byte's bit position.
+ *
+ *  @return  char*: Pointer to byte in which bit is contained.
+ */
+static char mask(int bit)
+{
+    char mask = (char)0x01;
+
+    // Ignore splint warning about negative bit shifts
+    /* @i@ */
+    mask = mask << (bit % 8);
+
+    return mask;
+}
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psBitSet* psBitSetAlloc(int n)
+{
+    int numBytes = 0;
+    psBitSet* newObj = NULL;
+
+    if (n <= 0) {
+        psError(__func__, " : Line %d - Allocation size must be > 0: size = %d", __LINE__, n);
+        return 0;
+    }
+
+    numBytes = ceil(n / 8.0);
+    newObj = psAlloc(sizeof(psBitSet));
+    if (newObj == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+    p_psMemSetDeallocator(newObj, (psFreeFcn) psBitSetFree);
+    newObj->n = numBytes;
+
+    // Ignore splint warning about releasing pointer members, since they've not been allocated yet
+    /* @i@ */
+    newObj->bits = psAlloc(sizeof(char) * numBytes);
+    if (newObj->bits == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    memset(newObj->bits, numBytes, 0);
+
+    return newObj;
+}
+
+static void psBitSetFree(psBitSet* restrict inBitSet)
+{
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return;
+    }
+    psFree(inBitSet->bits);
+}
+
+psBitSet* psBitSetSet(psBitSet* inBitSet, int bit)
+{
+    char *byte = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return inBitSet;
+    } else if (bit < 0) {
+        psError(__func__, " : Line %d - Bit position too small: %d", __LINE__, bit);
+        return inBitSet;
+    } else if (bit > inBitSet->n * 8 - 1) {
+        psError(__func__, " : Line %d - Bit position too large: %d", __LINE__, bit);
+        return inBitSet;
+    }
+    // Variable byte is the byte in the array that contains the bit to be set
+    byte = inBitSet->bits + bit / 8;
+    *byte |= mask(bit);
+
+    return inBitSet;
+}
+
+bool psBitSetTest(const psBitSet* inBitSet, int bit)
+{
+    char *byte = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return 0;
+    } else if (bit < 0) {
+        psError(__func__, " : Line %d - Bit position too small: %d", __LINE__, bit);
+        return 0;
+    } else if (bit > inBitSet->n * 8 - 1) {
+        psError(__func__, " : Line %d - Bit position too large: %d", __LINE__, bit);
+        return 0;
+    }
+    // Variable byte is the byte in the array that contains the bit to be tested
+    byte = inBitSet->bits + bit / 8;
+    if ((int)(*byte & mask(bit)) == 0) {
+        return 0;
+    }
+
+    return 1;
+}
+
+psBitSet* psBitSetOp(psBitSet* outBitSet, const psBitSet* restrict inBitSet1, char *operator,
+                     const psBitSet* restrict inBitSet2)
+{
+    int i = 0;
+    int n = 0;
+    char tempChar = '0';
+    char *outBits = NULL;
+    char *inBits1 = NULL;
+    char *inBits2 = NULL;
+
+    if (inBitSet1 == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet1 argument", __LINE__);
+        return outBitSet;
+    }
+
+    if (operator == NULL) {
+        psError(__func__, " : Line %d - Null input operator\n", __LINE__);
+        return outBitSet;
+    }
+
+    if (inBitSet2 == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet2 argument", __LINE__);
+        return outBitSet;
+    }
+
+    if (outBitSet == NULL) {
+        outBitSet = psBitSetAlloc(inBitSet1->n * 8);
+    }
+
+    if (inBitSet1->n != inBitSet2->n || outBitSet->n != inBitSet1->n) {
+        psError(__func__, " : Line %d - psBitSet sizes not the same", __LINE__);
+        return outBitSet;
+    }
+
+    n = outBitSet->n;
+    outBits = outBitSet->bits;
+    inBits1 = inBitSet1->bits;
+    inBits2 = inBitSet2->bits;
+
+    tempChar = toupper(operator[0]);
+    switch (tempChar) {
+    case 'A':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] & inBits2[i];
+        }
+        break;
+    case 'O':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] | inBits2[i];
+        }
+        break;
+    case 'X':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] ^ inBits2[i];
+        }
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psBitMask binary operation: %s", __LINE__, operator);
+    }
+
+    return outBitSet;
+}
+
+psBitSet* psBitSetNot(psBitSet* outBitSet, const psBitSet* restrict inBitSet)
+{
+    int i = 0;
+    int n = 0;
+    char *outBits = NULL;
+    char *inBits = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return outBitSet;
+    }
+
+    n = inBitSet->n;
+    if (n == 0) {
+        psError(__func__, " : Line %d - No elements in inBitSet", __LINE__);
+        return outBitSet;
+    }
+
+    if (outBitSet == NULL) {
+        outBitSet = psBitSetAlloc(n * 8);
+    }
+
+    if (inBitSet->n != outBitSet->n) {
+        psError(__func__, " : Line %d - psBitSet sizes not the same", __LINE__);
+        return outBitSet;
+    }
+
+    outBits = outBitSet->bits;
+    inBits = inBitSet->bits;
+
+    for (i = 0; i < n; i++) {
+        outBits[i] = ~inBits[i];
+    }
+
+    return outBitSet;
+}
+
+char *psBitSetToString(const psBitSet* restrict inBitSet)
+{
+    int i = 0;
+    int numBits = inBitSet->n * 8;
+    char *outString = psAlloc((size_t) numBits + 1);
+
+    if (outString == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    for (i = 0; i < numBits; i++) {
+        outString[numBits - i - 1] = (psBitSetTest(inBitSet, i) == 1) ? '1' : '0';
+    }
+
+    outString[numBits] = 0;
+
+    return outString;
+}
Index: /tags/rel2_1/psLib/src/collections/psBitSet.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psBitSet.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psBitSet.h	(revision 1553)
@@ -0,0 +1,134 @@
+
+/** @file  psBitSet.h
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @ingroup BitSet
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:53:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSBITSET_H
+#define PSBITSET_H
+
+/// @addtogroup BitSet
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Struct containing array of bytes to hold bit data and corresponding array length.
+ *
+ *  The bits in the struct are assembled in as an array of bytes with eight bits per byte. The bits are
+ *  arranged with the LSB in first (right most) position of the first array element.
+ */
+typedef struct
+{
+    int n;                             ///< Number of bytes in the array
+    char *bits;                        ///< Aray of bytes holding bits
+}
+psBitSet;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a psBitSet.
+ *
+ *  Create a psBitSet with the number of bits specified by the user. All bits are set to zero upon
+ *  allocation.
+ *
+ *  @return  psBitSet* : Pointer to struct containing array of bits and size of array.
+ */
+
+/*@null@*/
+psBitSet* psBitSetAlloc(
+    int n                              ///< Number of bits in psBitSet array
+);
+
+/** Set a bit.
+ *
+ *  Sets a bit at a given bit location, either one or zero. The bit is set based on a zero index with the
+ *  first bit set in the zero bit slot of the zero element of the byte array. As an example, setting bit 3 in
+ *  an array with two elements would result in an psBitSet that looks like 00000000 00001000.
+ *
+ *  @return  psBitSet* : Pointer to struct containing psBitSet.
+ */
+psBitSet* psBitSetSet(
+    /* @returned@ */
+    psBitSet* restrict inMask,         ///< Pointer to psBitSet to be set.
+    int bit                            ///< Bit to be set.
+);
+
+/** Test the value of a bit.
+ *
+ *  Prints the value of a bit at a given bit location, either one or zero. The resulting bit is based on a
+ *  zero index format with the first bit set in the zero bit slot of the zero element of the byte array
+ *  As an example, testing bit 3 in a psBitSet with two bytes that looks like 00000000 00001000 would return a
+ *  value of one, since that is the value that was set.
+ *
+ *  @return  int: Value of bit, either one or zero.
+ */
+
+bool psBitSetTest(
+    const psBitSet* restrict inMask,   ///< Pointer psBitSet to be tested.
+    int bit                            ///< Bit to be tested.
+);
+
+/** Perform a binary operation on two psBitSets
+ *
+ *  Perform an AND, OR, or XOR on two psBitSets. If the BitMasks are not the same size, the operation will not
+ *  be performed and an error message will be logged.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of binary operation.
+ */
+psBitSet* psBitSetOp(
+    /* @returned@ */
+    psBitSet* restrict outMask,        ///< Resulting psBitSet from binary operation
+    const psBitSet* restrict inMask1,  ///< First psBitSet on which to operate
+    char *operator,                    ///< Bit operation
+    const psBitSet* restrict inMask2   ///< First psBitSet on which to operate
+);
+
+/** Perform a not operation on a psBitSet
+ *
+ *  Toggles bits in a psBitset. All zero bits are set to one and all one bits are set to zero.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of operation.
+ */
+
+psBitSet* psBitSetNot(
+    psBitSet* outBitSet,               ///< Resulting psBitSet from operation
+    const psBitSet* restrict inBitSet  ///< Input psBitSet
+);
+
+/** Convert the psBitSet to a string of ones and zeros.
+ *
+ *  Converts the contents of a psBitSet to a string representation of its binary form of ones and zeros. The
+ *  LSB is the right-most chracter. Each set of eight characters represents one byte.
+ *
+ *  @return  char*: Pointer to character array containing string data.
+ */
+
+char *psBitSetToString(
+    const psBitSet* restrict inMask    ///< psBitSet to convert */
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psCompare.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psCompare.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psCompare.c	(revision 1553)
@@ -0,0 +1,80 @@
+
+/** @file psCompare.c
+ *  @brief Comparison functions for sorting routines
+ *  @ingroup Compare
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psType.h"
+#include "psCompare.h"
+
+#define COMPARE_NUMERIC_PTR(TYPE) \
+int psCompare##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)a) - **((ps##TYPE**)b); \
+}
+
+#define COMPARE_NUMERIC_PTR_DESCENDING(TYPE) \
+int psCompareDescending##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)b) - **((ps##TYPE**)a); \
+}
+
+#define COMPARE_NUMERIC(TYPE) \
+int psCompare##TYPE(const void* a, const void* b) { \
+    return *((ps##TYPE*)a) - *((ps##TYPE*)b); \
+}
+
+#define COMPARE_NUMERIC_DESCENDING(TYPE) \
+int psCompare##TYPE##Descending(const void* a, const void* b) { \
+    return *((ps##TYPE*)b) - *((ps##TYPE*)a); \
+}
+
+COMPARE_NUMERIC_PTR(S8)
+COMPARE_NUMERIC_PTR(S16)
+COMPARE_NUMERIC_PTR(S32)
+COMPARE_NUMERIC_PTR(S64)
+COMPARE_NUMERIC_PTR(U8)
+COMPARE_NUMERIC_PTR(U16)
+COMPARE_NUMERIC_PTR(U32)
+COMPARE_NUMERIC_PTR(U64)
+COMPARE_NUMERIC_PTR(F32)
+COMPARE_NUMERIC_PTR(F64)
+
+COMPARE_NUMERIC_PTR_DESCENDING(S8)
+COMPARE_NUMERIC_PTR_DESCENDING(S16)
+COMPARE_NUMERIC_PTR_DESCENDING(S32)
+COMPARE_NUMERIC_PTR_DESCENDING(S64)
+COMPARE_NUMERIC_PTR_DESCENDING(U8)
+COMPARE_NUMERIC_PTR_DESCENDING(U16)
+COMPARE_NUMERIC_PTR_DESCENDING(U32)
+COMPARE_NUMERIC_PTR_DESCENDING(U64)
+COMPARE_NUMERIC_PTR_DESCENDING(F32)
+COMPARE_NUMERIC_PTR_DESCENDING(F64)
+
+COMPARE_NUMERIC(S8)
+COMPARE_NUMERIC(S16)
+COMPARE_NUMERIC(S32)
+COMPARE_NUMERIC(S64)
+COMPARE_NUMERIC(U8)
+COMPARE_NUMERIC(U16)
+COMPARE_NUMERIC(U32)
+COMPARE_NUMERIC(U64)
+COMPARE_NUMERIC(F32)
+COMPARE_NUMERIC(F64)
+
+COMPARE_NUMERIC_DESCENDING(S8)
+COMPARE_NUMERIC_DESCENDING(S16)
+COMPARE_NUMERIC_DESCENDING(S32)
+COMPARE_NUMERIC_DESCENDING(S64)
+COMPARE_NUMERIC_DESCENDING(U8)
+COMPARE_NUMERIC_DESCENDING(U16)
+COMPARE_NUMERIC_DESCENDING(U32)
+COMPARE_NUMERIC_DESCENDING(U64)
+COMPARE_NUMERIC_DESCENDING(F32)
+COMPARE_NUMERIC_DESCENDING(F64)
Index: /tags/rel2_1/psLib/src/collections/psCompare.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psCompare.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psCompare.h	(revision 1553)
@@ -0,0 +1,506 @@
+#if !defined(PS_COMPARE_H)
+#define PS_COMPARE_H
+
+/** @file psCompare.h
+ *  @brief Comparison functions for sorting routines
+ *
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @ingroup Compare
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:58:11 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/** @addtogroup Compare
+*  @{
+*/
+
+/** A comparison function for sorting elements that are pointers to data,
+ *  e.g., for psList of pointers to numeric values.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+typedef int (*psComparePtrFcn) (
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** A comparison function for sorting.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+typedef int (*psCompareFcn) (
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psHash.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psHash.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psHash.c	(revision 1553)
@@ -0,0 +1,408 @@
+
+/** @file  psHash.c
+*
+*  @brief Contains support for basic hashing functions.
+*
+*  This file will hold the functions for defining a hash table with arbitrary
+*  data types, allocating/deallocating that hash table, adding and removing
+*  data from that hash table, and listing all keys defined in the hash table.
+*
+*  @author Robert Lupton, Princeton University
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include "psHash.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psTrace.h"
+#include "psAbort.h"
+
+static psHashBucket* hashBucketAlloc(const char *key, void *data, psHashBucket* next);
+static void hashBucketFree(psHashBucket* bucket);
+static void *doHashWork(psHash* table, const char *key, void *data, bool remove
+                           );
+static void hashFree(psHash* table);
+
+/******************************************************************************
+psHashKeyList(table): this function creates a linked list with an entry in
+that list for every key in the hash table.
+Inputs:
+    table: a hash table
+Return;
+    The linked list
+ *****************************************************************************/
+psList* psHashKeyList(psHash* table)
+{
+    int i = 0;                  // Loop index variable
+    psList* myLinkList = NULL;  // The output data structure
+    psHashBucket* ptr = NULL;   // Used to step thru linked list.
+
+    if (table == NULL) {
+        return NULL;
+    }
+    // Create the linked list
+    myLinkList = psListAlloc(NULL);
+
+    // Loop through every bucket in the hash table.  If that bucket is not
+    // NULL, then add the bucket's key to the linked list.
+    for (i = 0; i < table->nbucket; i++) {
+        if (table->buckets[i] != NULL) {
+            // Since a bucket contains a linked list of keys/data, we must
+            // step trough each key in that linked list:
+
+            ptr = table->buckets[i];
+            while (ptr != NULL) {
+                psListAdd(myLinkList, ptr->key, PS_LIST_HEAD);
+                ptr = ptr->next;
+            }
+        }
+    }
+
+    // Return the linked list
+    return (myLinkList);
+}
+
+/******************************************************************************
+hashBucketAlloc(key, data, next): This procedure creates a new hash bucket
+with the specified key, data, and next.
+Inputs:
+    key:  the new bucket's key pointer
+    data: the new bucket's data pointer
+    next: the new bucket's key pointer
+Return:
+    the new hash bucket.
+ *****************************************************************************/
+static psHashBucket* hashBucketAlloc(const char *key, void *data, psHashBucket* next)
+{
+    if (key == NULL) {
+        psAbort(__func__, "psHashBucket() called with NULL key.");
+    }
+    // Allocate memory for the new hash bucket.
+    psHashBucket* bucket = psAlloc(sizeof(psHashBucket));
+
+    p_psMemSetDeallocator(bucket, (psFreeFcn) hashBucketFree);
+
+    // Initialize the bucket.
+    bucket->key = psStringCopy(key);
+
+    if (data == NULL) {
+        // NOTE: Should we flag a warning message?
+        bucket->data = NULL;
+    } else {
+        bucket->data = psMemIncrRefCounter(data);
+    }
+
+    bucket->next = next;
+
+    return bucket;
+}
+
+/******************************************************************************
+hashBucketFree(bucket): This procedure deallocates the specified
+hash bucket.
+Inputs:
+    bucket: the hash bucket to be freed.
+Return:
+    NONE
+ *****************************************************************************/
+static void hashBucketFree(psHashBucket* bucket)
+{
+    if (bucket == NULL) {
+        return;
+    }
+
+    psFree(bucket->key);
+
+    psFree(bucket->data);
+}
+
+/******************************************************************************
+psHashAlloc(nbucket): this procedure creates a new hash table with the
+specified number of buckets.
+Inputs:
+    nbucket: initial number of buckets
+Return:
+    The new hash table.
+ *****************************************************************************/
+psHash* psHashAlloc(int nbucket)        // initial number of buckets
+{
+    int i = 0;                  // loop index variable
+
+    // Create the new hash table.
+    psHash* table = psAlloc(sizeof(psHash));
+
+    p_psMemSetDeallocator(table, (psFreeFcn) hashFree);
+
+    // Allocate memory for the buckets.
+    table->buckets = psAlloc(nbucket * sizeof(psHashBucket* ));
+    table->nbucket = nbucket;
+
+    psTrace("utils.hash", 1, "Creating %d-element hash table\n", nbucket);
+
+    // Initialize all buckets to NULL.
+    for (i = 0; i < nbucket; i++)
+    {
+        table->buckets[i] = NULL;
+    }
+
+    // Return the new hash table.
+    return table;
+}
+
+/******************************************************************************
+psHashFree(table, itemFree): This procedure deallocates the specified hash
+table.  It loops through each bucket, and calls hashBucketFree() on that
+bucket.
+ 
+Inputs:
+    table: a hash table
+Return:
+    NONE
+ *****************************************************************************/
+static void hashFree(psHash* table)
+{
+    int i = 0;                  // Loop index variable.
+
+    if (table == NULL) {
+        return;
+    }
+    // Loop through each bucket in the hash table.  If that bucket is not
+    // NULL, then free the bucket via a function call to hashBucketFree();
+    for (i = 0; i < table->nbucket; i++) {
+
+        // A bucket is composed of a linked list of buckets.
+        while (table->buckets[i] != NULL) {
+            psHashBucket* bucket = table->buckets[i];
+            table->buckets[i] = bucket->next;
+            psFree(bucket);
+        }
+    }
+
+    // Free the bucket structure, then the hash table.
+    psFree(table->buckets);
+}
+
+/******************************************************************************
+doHashWork(table, key, data, remove): This is an internal
+procedure which does the bulk of the work in using the hash table.  Depending
+upon the input parameters, it will either insert a new key/data into the hash
+table, retrieve the data for a specified key, or remove a key/data item.  If
+we try to insert a key that already exists in the hash table, then we deallocate
+the existing data/key item.
+Inputs:
+    table: a hash table
+    key: the key to insert, retrieve, or remove.  Must not be NULL.
+    data: the data to insert, if not NULL
+    remove: set to non-zero if the key/data should be removed from the table.
+Return:
+    NONE
+ 
+NOTE: consider removing this private function and simply putting the code
+into the psHashInsert(), psHashLookup(), and psHashRemove().  Why?  Because
+there is little common code between those functions.
+  *****************************************************************************/
+static void *doHashWork(psHash* table, const char *key, void *data, bool remove
+                           )
+{
+    long int hash = 1;          // This will contain an integer value
+
+    // "hashed" from the key.
+    char *tmpchar = NULL;       // Used in computing the hash function.
+    psHashBucket* ptr = NULL;   // Used to retrieve the hash bucket.
+    psHashBucket* optr = NULL;  // "original pointer": used to step
+
+    // thru the linked list for a bucket.
+
+    // The following condition should never be true, since this is a private
+    // function, but I'm checking it anyway since future coders might change
+    // the way this procedure is called.
+    if ((table == NULL) || (key == NULL)) {
+
+        psAbort(__func__, "psHashRemove() called with NULL key or table.");
+    }
+    // NOTE: This is the originally supplied hash function.
+    // for (int i = 0, len = strlen(key); i < len; i++) {
+    // hash = (hash << 1) ^ key[i];
+    // }
+    // hash &= (table->nbucket - 1);
+
+    // This hash algorithm is from Sedgewick.  NOTE: must reread to ensure that
+    // the size of the hash table is not required to be a prime number.
+    tmpchar = (char *)key;
+    for (hash = 0; *tmpchar != '\0'; tmpchar++) {
+        hash = (64 * hash + *tmpchar) % (table->nbucket);
+    }
+
+    // NOTE: This should not be necessary, but for now, I'm checking bounds
+    // anyway.
+    if ((hash < 0) || (hash >= table->nbucket)) {
+        psAbort(__func__, "Internal hash function out of range (%d)", hash);
+    }
+    // ptr will have the correct hash bucket.
+    ptr = table->buckets[hash];
+
+    // We know the correct hash bucket, now we need to know what to do.
+    // If the data parameter is NULL, then, by definition, this is a retrieve
+    // or a remove operation on the hash table.
+
+    if (data == NULL) {
+        if (remove
+           ) {
+            // We search through the linked list for this bucket in
+            // the hash table and look for an entry for this key.
+
+            optr = ptr;
+            while (ptr != NULL) {
+                // Determine if this entry holds the correct key.
+                if (strcmp(key, ptr->key) == 0) {
+                    // The following lines of code are fairly standard ways
+                    // of removing an item from a single-linked list.
+
+                    void *data = ptr->data;
+
+                    optr->next = ptr->next;
+                    if (ptr == table->buckets[hash]) {
+                        table->buckets[hash] = ptr->next;
+                    }
+                    psFree(ptr);
+
+                    // By definition, the data associated with that key
+                    // must be returned, not freed.
+                    return data;
+                }
+                optr = ptr;
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+        else {
+            // If we get here, then a retrieve operation is requested.  So,
+            // we step trough the linked list at this bucket, and return the
+            // data once we find it, or return NULL if we don't.
+            while (ptr != NULL) {
+                if (strcmp(key, ptr->key) == 0) {
+                    return ptr->data;
+                }
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+    } else {
+        // We get here if this procedure was called with non-NULL data.
+        // Therefore, we should insert that data into the hash table.
+        // First, we search through the linked list for this bucket in
+        // the hash table and look for a duplicate entry for this key.
+
+        while (ptr != NULL) {
+            if (strcmp(key, ptr->key) == 0) {
+                // We have found this key in the hash table.
+
+                psTrace("utils.hash.insert", 3, "Replacing data for %s\n", key);
+
+                // NOTE: I have changed this behavior from the originally
+                // supplied code.  Formerly, if itemFree was NULL, then
+                // the new data was not inserted into the hash table.
+
+                psFree(ptr->data);
+
+                ptr->data = psMemIncrRefCounter(data);
+                return data;
+            }
+            ptr = ptr->next;
+        }
+        // We did not found key in the linked list for this bucket of the hash
+        // table.  So, we insert this data at the head of that linked list.
+
+        table->buckets[hash] = hashBucketAlloc(key, data, table->buckets[hash]);
+        return data;
+    }
+}
+
+/******************************************************************************
+psHashInsert(table, key, data, itemFree): this procedure, which is part of
+the public API, inserts a new key/data pair into the hash table.
+Inputs:
+    table: a hash table
+    key: the key to use
+    data: the data to insert.
+    itemFree: a function pointer
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashAdd(psHash* table, const char *key, void *data)
+{
+    if (table == NULL) {
+        psAbort(__func__, "psHashInsert() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashInsert() called with NULL key.");
+    }
+    if (data == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL data.");
+    }
+
+    return (doHashWork(table, key, data, 0) != NULL);
+}
+
+/******************************************************************************
+psHashLookup(table, key): this procedure, which is part of the public API,
+looks up the specified key in the hash table and returns the data associated
+with that key.
+ 
+Inputs:
+    table: a hash table
+    key: the key to use
+Return:
+    The data associated with that key.
+ *****************************************************************************/
+void *psHashLookup(psHash* table,      // table to lookup key in
+                   const char *key)     // key to lookup
+{
+    if (table == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL key.");
+    }
+
+    return doHashWork(table, key, NULL, 0);
+}
+
+/******************************************************************************
+psHashRemove(table, key, itemFree): this procedure, which is part of the
+public API, removes the specified key from the hash table.
+Inputs:
+    table: a hash table
+    key: the key to remove
+    itemFree: a function pointer
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashRemove(psHash* table, const char *key)
+{
+    void *data = NULL;
+    bool retVal = false;
+
+    if (table == NULL) {
+        psAbort(__func__, "psHashRemove() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashRemove() called with NULL key.");
+    }
+
+    data = doHashWork(table, key, NULL, 1);
+    if (data != NULL) {
+        retVal = true;
+    } else {
+        retVal = false;
+    }
+    return retVal;
+}
Index: /tags/rel2_1/psLib/src/collections/psHash.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psHash.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psHash.h	(revision 1553)
@@ -0,0 +1,73 @@
+
+/** @file  psHash.h
+ *  @brief Contains support for basic hashing functions.
+ *  @ingroup HashTable
+ *
+ *  This file will hold the prototypes for defining a hash table with arbitrary
+ *  data types, allocating/deallocating that has table, adding and removing
+ *  data from that hash table, and listing all keys defined in the hash table.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *   
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_HASH_H)
+#define PS_HASH_H
+
+/** \addtogroup HashTable
+ *  \{
+ */
+#include<stdbool.h>
+
+#include "psList.h"
+
+/** A bucket that holds an item of data. */
+typedef struct psHashBucket
+{
+    char *key;                  ///< key for this item of data
+    void *data;                 ///< the data itself
+    struct psHashBucket* next;  ///< list of other possible keys
+}
+psHashBucket;
+
+//typedef struct HashTable psHash; ///< Opaque type for a hash table
+
+/** The hash-table itself. */
+typedef struct psHash
+{
+    int nbucket;                ///< Number of buckets in hash table.
+    psHashBucket* *buckets;     ///< The bucket data.
+}
+psHash;
+
+/// Allocate hash buckets in table.
+psHash* psHashAlloc(int nbucket ///< The number of buckets to allocate.
+                   );
+
+/// Insert entry into table.
+bool psHashAdd(psHash* table,  ///< table to insert in
+               const char *key, ///< key to use
+               void *data       ///< data to insert
+              );
+
+/// Lookup key in table.
+void *psHashLookup(psHash* table,      ///< table to lookup key in
+                   const char *key      ///< key to lookup
+                  );
+
+/// Remove key from table.
+bool psHashRemove(psHash* table,       ///< table to lookup key in
+                  const char *key       ///< key to lookup
+                 );
+
+/// List all keys in table.
+psList* psHashKeyList(psHash* table    ///< table to list keys from.
+                     );
+
+/* \} */// End of DataGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psList.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psList.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psList.c	(revision 1553)
@@ -0,0 +1,475 @@
+
+/** @file psList.c
+ *  @brief Support for doubly linked lists
+ *  @ingroup LinkedList
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-14 01:48:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <pthread.h>                       // we need a mutex to make this stuff thread safe.
+
+#include "psError.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psList.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+
+#define ITER_INIT_HEAD ((void *)1)         // next iteration should return head
+#define ITER_INIT_TAIL ((void *)2)         // next iteration should return tail
+
+// private functions.
+static psListElem* listGetIterator(psList* list);
+static int listGetIteratorIndex(psList* list);
+static void listSetIterator(psList* list, int where, bool lockList);
+static void listFree(psList* list);
+
+psList* psListAlloc(void *data)
+{
+    psList* list = psAlloc(sizeof(psList));
+
+    p_psMemSetDeallocator(list, (psFreeFcn) listFree);
+
+    list->size = 0;
+    list->head = list->tail = NULL;
+    list->iter = ITER_INIT_HEAD;
+    list->iterIndex = PS_LIST_HEAD;
+
+    pthread_mutex_init(&(list->lock), NULL)
+    ;
+
+    if (data != NULL) {
+        psListAdd(list, data, PS_LIST_TAIL);
+    }
+
+    return list;
+}
+
+static void listFree(psList* list)
+{
+    if (list == NULL) {
+        return;
+    }
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    for (psListElem* ptr = list->head; ptr != NULL;) {
+        psListElem* next = ptr->next;
+
+        psFree(ptr->data);
+        psFree(ptr);
+
+        ptr = next;
+    }
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    pthread_mutex_destroy(&list->lock)
+    ;
+
+}
+
+bool psListAdd(psList* list, void *data, int where)
+{
+    psListElem* position;
+    psListElem* elem;
+    int cursorIndex = 0;
+
+    if (list == NULL) {
+        return false;
+    }
+
+    if (data == NULL) {
+        return false;
+    }
+
+    if (where <= PS_LIST_UNKNOWN) {
+        // / XXX What is the better way to communicate this failure to the caller?
+        psLogMsg(__func__, PS_LOG_WARN, "The given insert location (%i) for psListAdd is invalid.", where);
+        return false;
+    }
+
+    elem = psAlloc(sizeof(psListElem));
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    if (where > 0 && where > list->size) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Invalid index %d (only %d elements in psList); assuming tail.", where, list->size);
+        where = PS_LIST_TAIL;
+    }
+
+    if (where == PS_LIST_TAIL || list->size == 0) {
+        // insert the element at the end of the list
+        elem->prev = list->tail;
+        elem->next = NULL;
+
+        if (list->tail != NULL) {
+            list->tail->next = elem;
+        }
+
+        if (list->head == NULL) {
+            list->head = elem;
+        }
+        list->tail = elem;
+
+        list->size++;
+        list->iter = elem;
+        list->iterIndex = list->size - 1;
+    } else {
+        // move ourselves to the given position
+        listSetIterator(list, where, false);
+        position = listGetIterator(list);
+        cursorIndex = listGetIteratorIndex(list);
+
+        if (position == NULL) {
+            psError(__func__, "%s failed to move cursor to specified location (%d)", __func__, where);
+            position = list->head;         // since we no list->size != 0, this must be non-NULL
+        }
+        // insert our new element in front of the given position
+        elem->prev = position->prev;
+        elem->next = position;
+        position->prev = elem;
+
+        if (elem->prev == NULL) {          // must be front of list
+            list->head = elem;
+        } else {
+            elem->prev->next = elem;
+        }
+
+        list->size++;
+        list->iter = elem;
+        list->iterIndex = cursorIndex;
+    }
+
+    elem->data = psMemIncrRefCounter(data);
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    return true;
+}
+
+/*****************************************************************************/
+
+/*
+ * Remove an element from a list
+ */
+bool psListRemove(psList* list, void *data, int which)
+{
+    psListElem* elem = NULL;    // element to remove
+    int cursorIndex = 0;
+
+    if (list == NULL) {
+        psError(__func__, "list parameter found to be NULL in %s", __func__);
+        return false;
+    }
+    // get exclusive access to list so that other threads will not get in the way.
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    if (which == PS_LIST_UNKNOWN) {
+        // search list for the data item.
+
+        int i = 0;              // index
+
+        for (psListElem* ptr = list->head; ptr != NULL; ptr = ptr->next) {
+            if (ptr->data == data) {
+                which = i;
+                break;
+            }
+            i++;
+        }
+
+        if (which == PS_LIST_UNKNOWN) {
+            psError(__func__, "Failed to find item in given psList.");
+            pthread_mutex_unlock(&list->lock)
+            ;
+            return false;
+        }
+    }
+    // position the list's cursor to the desired location
+    listSetIterator(list, which, false);
+    elem = listGetIterator(list);
+    cursorIndex = listGetIteratorIndex(list);
+
+    if (elem == NULL) {
+        psError(__func__, "Couldn't position to given index (%d) to remove element from list.", which);
+        pthread_mutex_unlock(&list->lock)
+        ;
+        return false;
+    }
+
+    list->size--;
+
+    if (elem->prev == NULL) {              // head of list?
+        list->head = elem->next;
+    } else {
+        elem->prev->next = elem->next;
+    }
+
+    if (elem->next == NULL) {              // tail of list?
+        list->tail = elem->prev;
+
+        // removed tail, so iter should be the last element of list to keep it valid
+        if (list->size > 0) {
+            list->iter = list->tail;
+            list->iterIndex = list->size - 1;
+        } else {
+            list->iter = ITER_INIT_TAIL;
+        }
+    } else {
+        elem->next->prev = elem->prev;
+        list->iter = elem->next;
+        list->iterIndex = cursorIndex;
+    }
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    // OK, delete list element and its data
+    psFree(elem->data);
+    psFree(elem);
+
+    return true;
+}
+
+void psListSetIterator(psList* list, int where)
+{
+    listSetIterator(list, where, true);
+}
+
+void listSetIterator(psList* list, int where, bool lockList)
+{
+    psListElem* cursor;
+    int position;
+
+    if (list == NULL) {
+        psError(__func__, "Unexpected null pointer for psList parameter (%s:%d).", __FILE__, __LINE__);
+        return;
+    }
+
+    if (where == PS_LIST_CURRENT) {
+        return;
+    }
+
+    if (lockList) {
+        pthread_mutex_lock(&list->lock)
+        ;
+        // don't want the list changing on us while we move about
+    }
+
+    if (where >= (int)list->size) {
+        list->iter = NULL;
+        if (lockList) {
+            pthread_mutex_unlock(&list->lock)
+            ;
+        }
+        return;
+    }
+
+    switch (where) {
+    case PS_LIST_HEAD:
+        list->iter = ITER_INIT_HEAD;
+        break;
+
+    case PS_LIST_TAIL:
+        list->iter = ITER_INIT_TAIL;
+        break;
+
+    case PS_LIST_PREVIOUS:
+        cursor = listGetIterator(list);
+        position = listGetIteratorIndex(list);
+
+        if (cursor != NULL) {
+            list->iter = cursor->prev;
+            list->iterIndex = position - 1;
+        }
+        break;
+
+    case PS_LIST_NEXT:
+        cursor = listGetIterator(list);
+        position = listGetIteratorIndex(list);
+
+        if (cursor != NULL) {
+            list->iter = cursor->next;
+            list->iterIndex = position + 1;
+        }
+        break;
+
+    case PS_LIST_CURRENT:
+        break;
+
+    default:
+        if (where <= PS_LIST_HEAD) {   // bascially same as PS_LIST_UNKNOWN above
+            psError(__func__, "Can't move to an unknown position.  Not moving the iterator position.");
+        } else {
+            cursor = listGetIterator(list);
+            if (cursor == NULL) {      // reset the iterator if it is invalid
+                list->iter = ITER_INIT_HEAD;
+                list->iterIndex = 0;
+            }
+
+            int position = listGetIteratorIndex(list);
+
+            if (where < position) {
+                int diff = position - where;
+
+                for (int count = 0; count < diff; count++) {
+                    listSetIterator(list, PS_LIST_PREVIOUS, false);
+                }
+            } else {
+                int diff = where - position;
+
+                for (int count = 0; count < diff; count++) {
+                    listSetIterator(list, PS_LIST_NEXT, false);
+                }
+            }
+        }
+        break;
+    }
+
+    if (lockList) {
+        pthread_mutex_unlock(&list->lock)
+        ;
+    }
+}
+
+psListElem* listGetIterator(psList* list)
+{
+    if (list == NULL) {
+        return NULL;
+    }
+
+    if (list->iter == ITER_INIT_HEAD) {
+        return list->head;
+    } else if (list->iter == ITER_INIT_TAIL) {
+        return list->tail;
+    } else {
+        return list->iter;
+    }
+}
+
+int listGetIteratorIndex(psList* list)
+{
+    if (list->iter == ITER_INIT_HEAD) {
+        return 0;
+    } else if (list->iter == ITER_INIT_TAIL) {
+        return list->size - 1;
+    } else {
+        return list->iterIndex;
+    }
+}
+
+void *psListGet(psList* list, int which)
+{
+    psListElem* element;
+
+    psListSetIterator(list, which);
+    element = listGetIterator(list);
+
+    if (element == NULL) {
+        return NULL;
+    } else {
+        return element->data;
+    }
+}
+
+/*
+ * and now return the previous/next element of the list
+ */
+void *psListGetNext(psList* list)
+{
+    return psListGet(list, PS_LIST_NEXT);
+}
+
+void *psListGetPrevious(psList* list)
+{
+    return psListGet(list, PS_LIST_PREVIOUS);
+}
+
+void *psListGetCurrent(psList* list)
+{
+    return psListGet(list, PS_LIST_CURRENT);
+}
+
+/*
+ * Convert a psList to/from a psVoidPtrArray
+ */
+psArray* psListToArray(psList* restrict list)
+{
+    psListElem* ptr;
+    unsigned int n;
+    psArray* restrict arr;
+
+    if (list == NULL) {
+        return NULL;
+    }
+
+    if (list->size > 0) {
+        arr = psArrayAlloc(list->size);
+    } else {
+        arr = psArrayAlloc(1);
+    }
+
+    arr->n = list->size;
+
+    ptr = list->head;
+    n = list->size;
+    for (int i = 0; i < n; i++) {
+        arr->data[i] = psMemIncrRefCounter(ptr->data);
+        ptr = ptr->next;
+    }
+
+    return arr;
+}
+
+psList* psArrayToList(psArray* arr)
+{
+    unsigned int n;
+    psList* list;               // list of elements
+
+    if (arr == NULL) {
+        return NULL;
+    }
+
+    list = psListAlloc(NULL);
+    n = arr->n;
+    for (int i = 0; i < n; i++) {
+        psListAdd(list, arr->data[i], PS_LIST_TAIL);
+    }
+
+    return list;
+}
+
+psList* psListSort(psList* list, psComparePtrFcn compare)
+{
+    psArray* arr;
+
+    if (list == NULL) {
+        return NULL;
+    }
+    // convert to indexable vector for use by qsort.
+    arr = psListToArray(list);
+    psFree(list);
+
+    arr = psArraySort(arr, compare);
+
+    // convert back to linked list
+    list = psArrayToList(arr);
+    psFree(arr);
+
+    return list;
+}
Index: /tags/rel2_1/psLib/src/collections/psList.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psList.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psList.h	(revision 1553)
@@ -0,0 +1,192 @@
+#if !defined(PS_LIST_H)
+#define PS_LIST_H
+
+/** @file psList.h
+ *  @brief Support for doubly linked lists
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @ingroup LinkedList
+ *
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:04:51 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
+#include <stdbool.h>                   // we use the bool type.
+
+#include "psCompare.h"
+#include "psArray.h"
+
+/** @addtogroup LinkedList
+ *  @{
+ */
+
+/** Special values of index into list
+ *
+ *  This list of possible list position values should be contiguous non-positive values ending with
+ *  PS_LIST_UNKNOWN.  Any value less-than-or-equal-to PS_LIST_UNKNOWN is considered a undefined position.
+ *
+ */
+enum {
+    PS_LIST_HEAD = 0,                  ///< at head
+    PS_LIST_TAIL = -1,                 ///< at tail
+    PS_LIST_PREVIOUS = -2,             ///< previous element
+    PS_LIST_CURRENT = -3,              ///< current element
+    PS_LIST_NEXT = -4,                 ///< next element
+    PS_LIST_UNKNOWN = -5               ///< unknown position (should be last in enum list)
+};
+
+/** Doubly-linked list element */
+typedef struct psListElem
+{
+    struct psListElem* prev;           ///< previous link in list
+    struct psListElem* next;           ///< next link in list
+    void *data;                        ///< real data item
+}
+psListElem;
+
+/** The psList Linked list structure.  User should not allocate this struct
+ *  directly; rather the psListAlloc should be used.
+ *
+ *  @see psListAlloc, psListFree
+ */
+typedef struct
+{
+    unsigned int size;                 ///< number of elements on list
+    psListElem* head;                  ///< first element on list (may be NULL)
+    psListElem* tail;                  ///< last element on list (may be NULL)
+    psListElem* iter;                  ///< iteration cursor
+    unsigned int iterIndex;            ///< the numeric position of the iteration cursor in the list
+    pthread_mutex_t lock;              ///< mutex to lock a node during changes
+}
+psList;
+
+/** Creates a psList linked list object.
+ *
+ *  @return psList* A new psList object.
+ */
+psList* psListAlloc(
+    void *data
+    ///< initial data item; may be NULL if no an empty psList is desired
+)
+;
+
+/** Adds an element to a psList at position given.
+ *
+ *  @return psList* The psList with added data item.  If list parameter is
+ *                      NULL, the return value will also be NULL.
+ */
+bool psListAdd(
+    psList* restrict list,             ///< list to add to (if NULL, nothing is done)
+    void *data,                        ///< data item to add.  If NULL, list is not modified.
+    int where                          ///< index, PS_LIST_HEAD, PS_LIST_TAIL, or numbered location.
+);
+
+/** Remove an item from a list.  If which parameter is PS_LIST_UNKNOWN,
+ *
+ *  @return bool        TRUE if element is successfully removed, otherwise FALSE.
+ */
+bool psListRemove(
+    psList* restrict list,
+    ///< list to remove element from
+    void *data,
+    ///< if which is PS_LIST_UNKNOWN, data item to find and remove, otherwise this is ignored.
+    int which
+    ///< index of item, or PS_LIST_UNKNOWN, PS_LIST_NEXT, PS_LIST_PREV, or numbered location.
+);
+
+/** Retrieve an item from a list.
+ *
+ *  @return void*       the item corresponding to the which parameter.  If
+ *                      which is invalid (e.g., a numbered index greater
+ *                      than the list size or if the list is empty), a
+ *                      NULL is returned.
+ */
+void *psListGet(
+    psList* restrict list,             ///< list to retrieve element from
+    int which                          ///< index number, or PS_LIST_NEXT, PS_LIST_PREV, PS_LIST_UNKNOWN
+);
+
+/** Set the iterator of the list to a given position.  If where is invalid the
+ *  iterator position is not changed.
+ *
+ */
+void psListSetIterator(
+    psList* restrict list,             ///< list to retrieve element from
+    int where                          ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Get next element relative to the iterator.  This also moves the iterator to
+ *  the next list position.
+ *
+ *  @return void*       the data item next on the list or NULL if the iterator
+ *                      is already pointing to the last element or the list
+ *                      parameter was NULL.
+ */
+void *psListGetNext(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Get current element according to the psList's iterator cursor.  This does
+ *  not move the iterator location.
+ *
+ *  @return void*       the data item cooresponding to current iterator
+ *                      cursor position of the list, or NULL if either the
+ *                      iterator is not valid or list parameter was NULL.
+ */
+void *psListGetCurrent(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Get previous element relative to list's iterator. This also moves the
+ *  iterator to the previous list position.
+ *
+ *  @return void*       the data item previous on the list or NULL if the iterator
+ *                      is already pointing to the first element or the list
+ *                      parameter was NULL.
+ */
+void *psListGetPrevious(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Convert a linked list to an array
+ *
+ *  @return psArray* A new psArray populated with elements from the list,
+ *                      or NULL if the given dlist parameter is NULL.
+ */
+psArray* psListToArray(
+    psList* dlist                      ///< List to convert
+);
+
+/** Convert array to a doubly-linked list
+ *
+ *  @return psList* A new psList populated with elements formt the psArray,
+ *                      or NULL is the given arr parameter is NULL.
+ */
+psList* psArrayToList(
+    psArray* arr                       ///< vector to convert
+);
+
+/** Sort a list via a comparison function.
+ *
+ *  The comparison function must return an integer less than, equal to, or 
+ *  greater than zero if the first argument is considered to be respectively 
+ *  less than, equal to, or greater than the second. 
+ *
+ *  If two members compare as equal, their order in the sorted array is 
+ *  undefined.
+ *
+ *  @return psList*     Sorted list.
+ */
+psList* psListSort(
+    psList* list,                      ///< the list to sort
+    psComparePtrFcn compare            ///< the comparison function
+);
+
+/// @} End of DataGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psMetadata.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psMetadata.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psMetadata.c	(revision 1553)
@@ -0,0 +1,761 @@
+
+/** @file  psMetadata.c
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-14 02:55:46 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include<stdio.h>
+#include<stdarg.h>
+#include<string.h>
+
+#include "fitsio.h"
+#include "psType.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psList.h"
+#include "psHash.h"
+#include "psMetadata.h"
+#include "psString.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+#define FITS_ERROR(STRING,PS_ERROR)                  \
+fits_get_errstatus(status, fitsErr);             \
+psError( __func__, STRING, PS_ERROR, fitsErr);   \
+status = 0;                                      \
+return output;
+
+/** Maximum size of a FITS line */
+#define FITS_LINE_SIZE 80
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH 1024
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+static int metadataId = 0;
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static void metadataItemFree(psMetadataItem* metadataItem)
+{
+    psMetadataType type;
+
+    type = metadataItem->type;
+
+    if (metadataItem == NULL) {
+        return;
+    }
+
+    psFree(metadataItem->name);
+    psFree(metadataItem->comment);
+    psFree(metadataItem->items);
+
+    if (type == PS_META_STR ||
+            type == PS_META_IMG ||
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+        psFree(metadataItem->data.V);
+    }
+}
+
+static void metadataFree(psMetadata* metadata)
+{
+    if (metadata == NULL) {
+        return;
+    }
+    psFree(metadata->list);
+    psFree(metadata->table);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+psMetadataItem* psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    // Get the variable list parameters to pass to allocation function
+    va_start(argPtr, comment);
+
+    // Call metadata item allocation
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    return metadataItem;
+}
+
+psMetadataItem* psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment,
+                                     va_list argPtr)
+{
+    psMetadataItem* metadataItem = NULL;
+
+    if (name == NULL) {
+        psError(__func__, "Null value for name not allowed");
+        return NULL;
+    }
+    // Allocate metadata item
+    metadataItem = (psMetadataItem* ) psAlloc(sizeof(psMetadataItem));
+    if (metadataItem == NULL) {
+        psAbort(__func__, "Failed to allocate memory");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
+
+    // Allocate and set metadata item comment
+    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    if (comment == NULL) {
+        // Per SDRS, null isn't allowed, must use "" instead
+        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
+    } else {
+        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
+    }
+
+    // Set metadata item unique id
+    *(int *)(&metadataItem->id) = ++metadataId;
+
+    // Set metadata item type
+    metadataItem->type = type;
+
+    // Set metadata item value
+    switch (type) {
+    case PS_META_ITEM_SET:
+        metadataItem->data.V = NULL;
+        break;
+    case PS_META_BOOL:
+        metadataItem->data.B = (bool)va_arg(argPtr, int);
+        break;
+    case PS_META_S32:
+        metadataItem->data.S32 = va_arg(argPtr, psS32);
+        break;
+    case PS_META_F32:
+        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
+        break;
+    case PS_META_F64:
+        metadataItem->data.F64 = va_arg(argPtr, psF64);
+        break;
+    case PS_META_STR:
+        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, "Invalid psMetadataType: %d", type);
+    }
+
+    // Allocate and set metadata item name
+    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    vsprintf(metadataItem->name, name, argPtr);
+
+    // Allocate metadata items with same name.
+    metadataItem->items = psListAlloc(NULL);
+
+    return metadataItem;
+}
+
+psMetadata* psMetadataAlloc(void)
+{
+    psList* list = NULL;
+    psHash* table = NULL;
+    psMetadata* metadata = NULL;
+
+    // Allocate metadata
+    metadata = (psMetadata* ) psAlloc(sizeof(psMetadata));
+    if (metadata == NULL) {
+        psAbort(__func__, "Failed to allocate metadata");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadata, (psFreeFcn) metadataFree);
+
+    // Allocate metadata's internal containers
+    list = (psList* ) psListAlloc(NULL);
+    if (list == NULL) {
+        psAbort(__func__, "Failed to allocate list");
+    }
+
+    table = (psHash* ) psHashAlloc(10);
+    if (table == NULL) {
+        psAbort(__func__, "Failed to allocate table");
+    }
+
+    metadata->list = list;
+    metadata->table = table;
+
+    return metadata;
+}
+
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
+    psHash *mdTable = NULL;
+    psList *mdList = NULL;
+    psMetadataItem *existingEntry = NULL;
+    psMetadataItem *newFolderEntry = NULL;
+    psMetadataType newType = PS_META_ITEM_SET;
+
+    if(md == NULL) {
+        psError( __func__, "Null metadata collection not allowed" );
+        return false;
+    }
+
+    if(metadataItem == NULL) {
+        psError( __func__, "Null metadata item not allowed" );
+        return false;
+    }
+
+    newType = metadataItem->type;
+
+    mdTable = md->table;
+    if(mdTable == NULL) {
+        psError( __func__, "Null metadata table not allowed" );
+        return false;
+    }
+
+    mdList = md->list;
+    if(mdList == NULL) {
+        psError( __func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    key = metadataItem->name;
+    if(key == NULL) {
+        psError(__func__, "Null key item not allowed");
+        return false;
+    }
+
+    // See if key is already in table
+    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+    if(existingEntry != NULL) {
+
+        if(existingEntry->type == PS_META_ITEM_SET) {
+
+            // Add leaf node to existing folder node
+            if(!psListAdd(existingEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                         metadataItem->name );
+                return false;
+            }
+        } else if(existingEntry->type != PS_META_ITEM_SET && newType!= PS_META_ITEM_SET) {
+
+            // Leaf node replaces another leaf. Make new folder node and add leaves.
+            newFolderEntry = psMetadataItemAlloc(key, PS_META_ITEM_SET, NULL, NULL);
+
+            if(!psListAdd(newFolderEntry->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psListAdd(newFolderEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, newFolderEntry)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            // Remove local reference to new folder node
+            psMemDecrRefCounter(newFolderEntry);
+        } else {
+
+            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
+            if(!psListAdd(metadataItem->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, metadataItem)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                return false;
+            }
+        }
+    } else {
+
+        // Node doesn't exist - Add new metadata item to metadata collection's hash
+        if(!psHashAdd(mdTable, key, metadataItem)) {
+            psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+            return false;
+        }
+    }
+
+    // Add all items to metadata collection's list, even if they have the same metadata item names
+    if(!psListAdd( mdList, metadataItem, where )) {
+        psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                 metadataItem->name );
+        return false;
+    }
+
+    return true;
+}
+
+bool psMetadataAdd(psMetadata* restrict md, int where, const char *name, psMetadataType type,
+                   const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    va_start(argPtr, comment);
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+    va_end(argPtr);
+
+    if (!psMetadataAddItem(md, where, metadataItem)) {
+        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                metadataItem->name);
+        psFree(metadataItem);
+        return false;
+    }
+    // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
+    // here
+    psMemDecrRefCounter(metadataItem);
+
+    return true;
+}
+
+
+
+bool psMetadataRemove(psMetadata* restrict md, int where, const char *restrict key)
+{
+    int numChildren = 0;
+    psList* mdList = NULL;
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+    psMetadataItem* entryChild = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return false;
+    }
+    // Select removal by key or index
+    if (key != NULL) {
+
+        // Remove by key name
+        entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item. Name: %s", key);
+            return false;
+        }
+
+        numChildren = entry->items->size;
+        if (entry->type == PS_META_ITEM_SET && numChildren > 0) {
+
+            // Table entry has children. Entry and children must be removed from metadata collection's list
+            psListSetIterator(entry->items, PS_LIST_HEAD);
+            entryChild = psListGetCurrent(entry->items);
+            while (entryChild != NULL) {
+                if (!psListRemove(mdList, entryChild, PS_LIST_UNKNOWN)) {
+                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                    return false;
+                }
+                entryChild = psListGetNext(entry->items);
+            }
+        } else {
+
+            // Table entry has no children. Remove entry from metadata collection's list
+            if (!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
+                psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                return false;
+            }
+        }
+        // Remove entry from metadata collection's table
+        if (!psHashRemove(mdTable, key)) {
+            psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
+            return false;
+        }
+    } else {
+
+        // Remove by index
+        entry = psListGet(mdList, where);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item in list. Index: %d", where);
+            return false;
+        }
+
+        key = entry->name;
+        if (key == NULL) {
+            psError(__func__, "Null key name not allowed. Index: %d", where);
+            return false;
+        }
+        // Use recursive remove, now that key is known
+        psMetadataRemove(md, PS_LIST_UNKNOWN, key);
+    }
+
+    return true;
+}
+
+psMetadataItem* psMetadataLookup(psMetadata* restrict md, const char *restrict key)
+{
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return NULL;
+    }
+
+    if (key == NULL) {
+        psError(__func__, "Null key name not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+    if (entry == NULL) {
+        psError(__func__, "Could not find metadata item. Key: %s", key);
+        return NULL;
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGet(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psListGet(mdList, where);
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item with given index. Index: %d", where);
+        return NULL;
+    }
+
+    return entry;
+}
+
+bool psMetadataSetIterator(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    psListSetIterator(mdList, where);
+
+    return true;
+}
+
+psMetadataItem* psMetadataGetNext(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetNext(mdList);
+        } else {
+            return psListGetNext(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item");
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGetPrevious(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetPrevious(mdList);
+        } else {
+            return psListGetPrevious(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item", match);
+    }
+
+    return entry;
+}
+
+void psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* restrict metadataItem)
+{
+    psMetadataType type;
+
+    if (fd == NULL) {
+        psError(__func__, "Null file descriptor not allowed");
+        return;
+    }
+
+    if (format == NULL) {
+        psError(__func__, "Null format not allowed");
+        return;
+    }
+
+    if (metadataItem == NULL) {
+        psError(__func__, "Null metadata not allowed");
+        return;
+    }
+
+    type = metadataItem->type;
+
+    switch (type) {
+    case PS_META_BOOL:
+        fprintf(fd, format, metadataItem->data.B);
+        break;
+    case PS_META_S32:
+        fprintf(fd,format, metadataItem->data.S32);
+        break;
+    case PS_META_F32:
+        fprintf(fd, format, metadataItem->data.F32);
+        break;
+    case PS_META_F64:
+        fprintf(fd, format, metadataItem->data.F64);
+        break;
+    case PS_META_STR:
+        fprintf(fd, format, metadataItem->data.V);
+        break;
+    case PS_META_ITEM_SET:
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, " Invalid psMetadataType to print: %d", type);
+    }
+}
+
+psMetadata* psMetadataFReadHeader(psMetadata* output, char *extName, int extNum, fitsfile * fd)
+{
+    bool tempBool;
+    bool success;
+    char keyType;
+    char keyName[FITS_LINE_SIZE];
+    char keyValue[FITS_LINE_SIZE];
+    char keyComment[FITS_LINE_SIZE];
+    char fitsErr[MAX_STRING_LENGTH];
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    int keyNum = 0;
+    psMetadataType metadataItemType;
+
+    if (fd == NULL) {
+        psError(__func__, "Null FITS file descriptor not allowed");
+        return NULL;
+    }
+
+    if (extName == NULL && extNum == 0) {
+        psError(__func__, "Null extName and extNum = 0 not allowed");
+        return NULL;
+    } else if (extName && extNum) {
+        psError(__func__, "Both extName and extNum arguments should not have non zero values.");
+        return NULL;
+    }
+    // Allocate metadata if user didn't
+    if (output == NULL) {
+        output = psMetadataAlloc();
+    }
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if (extName != NULL) {
+        if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %s: %s", extName);
+        }
+    } else {
+        if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %d: %s", extNum);
+        }
+    }
+
+    // Get number of key names
+    if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
+        FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+    }
+    // Get each key name. Keywords start at one.
+    for (i = 1; i <= numKeys; i++) {
+        if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
+            FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+        }
+        if (fits_get_keytype(keyValue, &keyType, &status) != 0) {
+            fits_get_errstatus(status, fitsErr);
+            if (status != VALUE_UNDEFINED) {
+                FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
+            } else {
+                // Some keywords are still valid even though they don't have a type, like COMMENTS and
+                // HISTORY
+                keyType = 'C';
+                status = 0;
+            }
+        }
+
+        switch (keyType) {
+        case 'I':
+            metadataItemType = PS_META_S32;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atoi(keyValue));
+            break;
+        case 'F':
+            metadataItemType = PS_META_F64;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atof(keyValue));
+            break;
+        case 'C':
+            metadataItemType = PS_META_STR;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, keyValue);
+            break;
+        case 'L':
+            metadataItemType = PS_META_BOOL;
+            tempBool = (keyValue[0] == 'T') ? 1 : 0;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, tempBool);
+            break;
+        case 'U':
+        case 'X':
+        default:
+            psError(__func__, "Invalid psMetadataType: %c", keyType);
+            return output;
+        }
+
+        if (!success) {
+            psError(__func__, "Failed to add metadata item. Name: %s", keyName);
+            return output;
+        }
+    }
+
+    return output;
+}
Index: /tags/rel2_1/psLib/src/collections/psMetadata.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psMetadata.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psMetadata.h	(revision 1553)
@@ -0,0 +1,298 @@
+
+/** @file  psMetadata.h
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 01:23:20 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#ifndef PS_METADATA_H
+#define PS_METADATA_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <fitsio.h>
+
+#include "psHash.h"
+#include "psList.h"
+
+/// @addtogroup Metadata
+/// @{
+
+/** Metadata item type.
+ *
+ * Enumeration for maintaining metadata item types.
+ */
+typedef enum {
+    PS_META_ITEM_SET = 0,              ///< Null. Metadata is in psMetadataItem.items
+    PS_META_BOOL,                      ///< Boolean data.
+    PS_META_S32,                       ///< Signed 32-bit integer data.
+    PS_META_F32,                       ///< Single-precision float data.
+    PS_META_F64,                       ///< Double-precision float data.
+    PS_META_STR,                       ///< String data (Stored in as void *).
+    PS_META_IMG,                       ///< Image data (Stored in as void *).
+    PS_META_JPEG,                      ///< JPEG data (Stored in as void *).
+    PS_META_PNG,                       ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                   ///< Other data (Stored in as void *).
+    PS_META_NTYPE                      ///< Number of types. Must be last.
+} psMetadataType;
+
+/** Metadata item data structure.
+ *
+ * Struct for maintaining metadata items of varying types. It also contains
+ * information about the item name, flags, comments, and other items with the same name.
+ */
+typedef struct psMetadataItem
+{
+    const int id;                      ///< Unique ID for metadata item.
+    char *restrict name;               ///< Name of metadata item.
+    psMetadataType type;               ///< Type of metadata item.
+    union {
+        bool B;                        ///< boolean data
+        psS32 S32;                     ///< Signed 32-bit integer data.
+        psF32 F32;                     ///< Single-precision float data.
+        psF64 F64;                     ///< Double-precision float data.
+        psPTR V;                       ///< Pointer to other type of data.
+    } data;                            ///< Union for data types.
+    char *comment;                     ///< Optional comment ("", not NULL).
+    psList* restrict items;            ///< List of psMetadataItems with same name.
+}
+psMetadataItem;
+
+/** Metadata data structure.
+ *
+ *  Struct for holding metadata items. Metadata items are held in two 
+ *  containers. The first employs a doubly-linked list to preserve the order 
+ *  of the metadata. The second container employs a hash table which
+ *  allows fast lookup when given a metadata keyword.
+ */
+typedef struct psMetadata
+{
+    psList* restrict list;             ///< the metadata in linked-list
+    psHash* restrict table;            ///< the metadata in a hash table
+}
+psMetadata;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Create a metadata item.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and 
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAlloc(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata item with va_list.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocV(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata collection.
+ *
+ *  Returns an empty metadata container with fully allocated internal metadata 
+ *  containers.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataAlloc(void);
+
+/** Add existing metadata item to metadata collection.
+ *
+ *  Add a metadata item that has already been created to the metadata 
+ *  collection.
+ *
+ *  @return bool: True for success, false for failure.
+ */
+bool psMetadataAddItem(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    psMetadataItem* restrict item      ///< Metadata item to be added.
+);
+
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataAdd(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Remove an item from metadata collection.
+ *
+ *  Items may be removed from metadata by specifing a key or location. If the 
+ *  name is null, the where argument is used instead. If name is not null, 
+ *  where is set to PS_LIST_UNKNOWN. If the item is found, it is removed from 
+ *  the metadata and true is returned.  If the key is not unique, then all 
+ *  items corresponding to it are removed.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataRemove(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be removed.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on key name.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is 
+ *  non-unique, the first item is returned. If the item is not found, null is 
+ *  returned.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataLookup(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadata item.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on list index.
+ *
+ *  Items may be found in the metadata by their entry position in the list 
+ *  container.
+ *
+ *  @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGet(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where                          ///< Location to be retrieved.
+);
+
+/** Set or reset metadata iterator.
+ *
+ *  Metadata may be iterated by setting or resetting an iterator to a location 
+ *  in the metadata list.
+ *
+ * @return void: void.
+ */
+bool psMetadataSetIterator(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    int where                          ///< Location of iterator.
+);
+
+/** Get next metadata item.
+ *
+ * Get next metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetNext(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Get previous metadata item.
+ *
+ * Get previous metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetPrevious(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Print metadata item to file.
+ *
+ *  Metadata items may be printed to an open file descriptor based on a 
+ *  provided format. The format is a sprintf format statement with exactly 
+ *  one % formatting command. If the metadata item type is a numeric type, 
+ *  this formatting command must also be numeric, and the type conversion 
+ *  performed to the value to match the format type. If the metadata type is 
+ *  a string, the fromatting command must also be for a string. If the
+ *  metadata type is any other data type, printing is not allowed.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+void psMetadataItemPrint(
+    FILE * fd,                         ///< Pointer to file to write metadata item.
+    const char *format,                ///< Format to print metadata item.
+    const psMetadataItem* restrict metadataItem ///< Metadata item to print.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported. This file is currently unimplemented.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extname,                     ///< File name extension string.
+    int extnum,                        ///< File name extension number. Starts at 1.
+    char *filename                     ///< Name of file to read.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataFReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extName,                     ///< File name extension string.
+    int extNum,                        ///< File name extension number.
+    fitsfile * fd                      ///< Pointer to file to read.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psScalar.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psScalar.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psScalar.c	(revision 1553)
@@ -0,0 +1,153 @@
+
+/** @file  psScalar.c
+ *
+ *  @brief Contains basic scalar definitions and operations
+ *
+ *  This file defines the basic type for a scalar struct and functions useful
+ *  in manupulating scalars.
+ * *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 19:27:47 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include "psMemory.h"
+#include "psError.h"
+#include "psScalar.h"
+#include "psLogMsg.h"
+#include "psAbort.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psScalar* psScalarAlloc(psC64 value, psElemType dataType)
+{
+    psScalar* scalar = NULL;
+
+    // Create scalar
+    scalar = (psScalar* ) psAlloc(sizeof(psScalar));
+    if (scalar == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    scalar->type.dimen = PS_DIMEN_SCALAR;
+    scalar->type.type = dataType;
+
+    switch (dataType) {
+    case PS_TYPE_S8:
+        scalar->data.S8 = (psS8) value;
+        break;
+    case PS_TYPE_U8:
+        scalar->data.U8 = (psU8) value;
+        break;
+    case PS_TYPE_S16:
+        scalar->data.S16 = (psS16) value;
+        break;
+    case PS_TYPE_U16:
+        scalar->data.U16 = (psU16) value;
+        break;
+    case PS_TYPE_S32:
+        scalar->data.S32 = (psS32) value;
+        break;
+    case PS_TYPE_U32:
+        scalar->data.U32 = (psU32) value;
+        break;
+    case PS_TYPE_S64:
+        scalar->data.S64 = (psS64) value;
+        break;
+    case PS_TYPE_U64:
+        scalar->data.U64 = (psU64) value;
+        break;
+    case PS_TYPE_F32:
+        scalar->data.F32 = (psF32) value;
+        break;
+    case PS_TYPE_F64:
+        scalar->data.F64 = (psF64) value;
+        break;
+    case PS_TYPE_C32:
+        scalar->data.C32 = (psC32) value;
+        break;
+    case PS_TYPE_C64:
+        scalar->data.C64 = (psC64) value;
+        break;
+    default:
+        psError(__func__, ": Line %d - Invalid PS_TYPE: %d", __LINE__, dataType);
+    }
+
+    return scalar;
+}
+
+psScalar* psScalarCopy(psScalar *scalar)
+{
+    psScalar *newScalar = NULL;
+
+    if (scalar == NULL) {
+        psError(__func__, "Null scalar not allowed");
+    }
+
+    newScalar =  psScalarAlloc(scalar->data.C64, scalar->type.type);
+    if (newScalar == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    return newScalar;
+}
+
+void psScalarFree(psScalar* restrict scalar)
+{
+    if (scalar == NULL) {
+        return;
+    }
+
+    psFree(scalar);
+}
Index: /tags/rel2_1/psLib/src/collections/psScalar.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psScalar.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psScalar.h	(revision 1553)
@@ -0,0 +1,93 @@
+
+/** @file  psScalar.h
+ *
+ *  @brief Contains basic scalar definitions and operations
+ *
+ *  This file defines the basic type for a scalar struct and functions useful
+ *  in manupulating scalars.
+ *
+ *  @ingroup Scalar
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:08:08 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_SCALAR_H
+#define PS_SCALAR_H
+
+#include "psType.h"
+
+/// @addtogroup Scalar
+/// @{
+
+/** Basic scalar data structure.
+ *
+ * Struct for maintaining a scalar of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psType type;                ///< Type of data.
+
+    union {
+        psU8 U8;                ///< Unsigned 8-bit integer data.
+        psU16 U16;              ///< Unsigned 16-bit integer data.
+        psU32 U32;              ///< Unsigned 32-bit integer data.
+        psU64 U64;              ///< Unsigned 64-bit integer data.
+        psS8 S8;                ///< Signed 8-bit integer data.
+        psS16 S16;              ///< Signed 16-bit integer data.
+        psS32 S32;              ///< Signed 32-bit integer data.
+        psS64 S64;              ///< Signed 64-bit integer data.
+        psF32 F32;              ///< Single-precision float data.
+        psF64 F64;              ///< Double-precision float data.
+        psC32 C32;              ///< Single-precision complex data.
+        psC64 C64;              ///< Double-precision complex data.
+    } data;                     ///< Union for data types.
+}
+psScalar;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a scalar.
+ *
+ * Uses psLib memory allocation functions to create scalar data as defined by the psType type.
+ * Accepts a complex 64 bit float for input value, as max size, but resizes according to
+ * correct type.
+ *
+ * @return psScalar*   Pointer to a new psScalar.
+ */
+psScalar* psScalarAlloc(
+    psC64 value,                       ///< Data to be put into psScalar.
+    psElemType dataType                ///< Type of data to be held by psScalar.
+);
+
+/** Deallocate a scalar.
+ *
+ * Uses psLib memory allocation functions to deallocate a scalar.
+ *
+ */
+void psScalarFree(
+    psScalar* restrict scalar          ///< Scalar to free.
+);
+
+/** Copy a scalar.
+ *
+ * Uses psLib memory allocation functions to copy a scalar.
+ *
+ * @return psScalar*    A copy of the input scalar
+ */
+psScalar* psScalarCopy(
+    psScalar *scalar                   ///< Scalar to copy.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/collections/psVector.c
===================================================================
--- /tags/rel2_1/psLib/src/collections/psVector.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psVector.c	(revision 1553)
@@ -0,0 +1,357 @@
+
+/** @file  psVector.c
+*
+*  @brief Contains support for basic vector types
+*
+*  This file defines the basic type for a vector struct and functions useful
+*  in manupulating vectors.
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>                        // for memcpy
+#include <stdlib.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psVector.h"
+#include "psLogMsg.h"
+#include "psCompare.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void vectorFree(psVector* restrict psVec);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psVector* psVectorAlloc(unsigned int nalloc, psElemType elemType)
+{
+    psVector* psVec = NULL;
+    int elementSize = 0;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);
+        return NULL;
+    }
+
+    elementSize = PSELEMTYPE_SIZEOF(elemType);
+
+    // Create vector struct
+    psVec = (psVector* ) psAlloc(sizeof(psVector));
+    p_psMemSetDeallocator(psVec, (psFreeFcn) vectorFree);
+
+    psVec->type.dimen = PS_DIMEN_VECTOR;
+    psVec->type.type = elemType;
+    psVec->nalloc = nalloc;
+    psVec->n = nalloc;
+
+    // Create vector data array
+    psVec->data.V = psAlloc(nalloc * elementSize);
+
+    return psVec;
+}
+
+psVector* psVectorRealloc(unsigned int nalloc, psVector* restrict in)
+{
+    int elementSize = 0;
+    psElemType elemType;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for realloc (%d)\n", nalloc);
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "Null input vector\n");
+        return NULL;
+    } else if (in->nalloc != nalloc) {     // No need to realloc to same size
+        elemType = in->type.type;
+        elementSize = PSELEMTYPE_SIZEOF(elemType);
+        if (nalloc < in->n) {
+            in->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        in->data.V = psRealloc(in->data.V, nalloc * elementSize);
+        in->nalloc = nalloc;
+    }
+
+    return in;
+}
+
+psVector* psVectorRecycle(psVector* restrict in, unsigned int nalloc, psElemType type)
+{
+    psElemType elemType;
+
+    if (in == NULL) {
+        return psVectorAlloc(nalloc, type);
+    }
+
+    elemType = in->type.type;
+
+    if (in->nalloc == nalloc && elemType == type) {
+        // it is proper size/type already
+        return in;
+    }
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc (%d)\n", nalloc);
+        psFree(in);
+        return NULL;
+    }
+
+    in->data.V = psRealloc(in->data.V, nalloc * PSELEMTYPE_SIZEOF(type));
+
+    in->type.type = type;
+    in->nalloc = nalloc;
+    in->n = nalloc;
+
+    return in;
+}
+
+psVector* psVectorSort(psVector* restrict outVector, const psVector* restrict inVector)
+{
+    int inN = 0;
+    int outN = 0;
+    int elSize = 0;
+    void *inVec = NULL;
+    void *outVec = NULL;
+    psElemType inType = 0;
+
+    if (inVector == NULL) {
+        psError(__func__, " : Line %d - Null input vector\n", __LINE__);
+        return outVector;
+    }
+
+    inType = inVector->type.type;
+    inN = inVector->n;
+    inVec = inVector->data.V;
+    elSize = PSELEMTYPE_SIZEOF(inType);
+
+    if (outVector == NULL) {
+        outVector = psVectorAlloc(inN, inType);
+        outVector->n = inVector->n;
+    }
+
+    outN = outVector->n;
+    outVec = outVector->data.V;
+
+    if (inN != outN) {
+        psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",
+                __LINE__, inN, outN);
+        return outVector;
+    }
+
+    if (inType != outVector->type.type) {
+        psError(__func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__,
+                inType, outVector->type.type);
+        return outVector;
+    }
+
+    if (inN == 0) {
+        psError(__func__, " : Line %d - No elements in use for input vector\n", __LINE__);
+        return outVector;
+    }
+
+    if (outN == 0) {
+        psError(__func__, " : Line %d - No elements in use for output vector\n", __LINE__);
+        return outVector;
+    }
+    // Copy input vector values into output vector
+    memcpy(outVec, inVec, elSize * outN);
+
+    // Sort output vector
+    switch (inType) {
+    case PS_TYPE_U8:
+        qsort(outVec, inN, elSize, psCompareU8);
+        break;
+    case PS_TYPE_U16:
+        qsort(outVec, inN, elSize, psCompareU16);
+        break;
+    case PS_TYPE_U32:
+        qsort(outVec, inN, elSize, psCompareU32);
+        break;
+    case PS_TYPE_U64:
+        qsort(outVec, inN, elSize, psCompareU64);
+        break;
+    case PS_TYPE_S8:
+        qsort(outVec, inN, elSize, psCompareS8);
+        break;
+    case PS_TYPE_S16:
+        qsort(outVec, inN, elSize, psCompareS16);
+        break;
+    case PS_TYPE_S32:
+        qsort(outVec, inN, elSize, psCompareS32);
+        break;
+    case PS_TYPE_S64:
+        qsort(outVec, inN, elSize, psCompareS64);
+        break;
+    case PS_TYPE_F32:
+        qsort(outVec, inN, elSize, psCompareF32);
+        break;
+    case PS_TYPE_F64:
+        qsort(outVec, inN, elSize, psCompareF64);
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
+    }
+
+    return outVector;
+}
+
+#define SORT_INDICES(TYPE)                                                                                   \
+for(i=0; i<inN; i++) {                                                                                       \
+    for(j=0; j<inN; j++) {                                                                                   \
+        diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]);                                             \
+        if(diff < FLT_EPSILON) {                                                                             \
+            outVec[i] = j;                                                                                   \
+            break;                                                                                           \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+psVector* psVectorSortIndex(psVector* restrict outVector, const psVector* restrict inVector)
+{
+    int inN = 0;
+    int outN = 0;
+    int i = 0;
+    int j = 0;
+    float *inVec = NULL;
+    int *outVec = NULL;
+    double diff = 0.0f;
+    psVector* tmpVector = NULL;
+    psElemType inType = 0;
+
+    if (inVector == NULL) {
+        psError(__func__, " : Line %d - Null input vector\n", __LINE__);
+        return outVector;
+    }
+
+    inN = inVector->n;
+    inVec = inVector->data.V;
+    inType = inVector->type.type;
+
+    if (outVector == NULL) {
+        outVector = psVectorAlloc(inN, PS_TYPE_U32);
+        outVector->n = inN;
+    }
+
+    outN = outVector->n;
+    outVec = outVector->data.V;
+
+    if (inN != outN) {
+        psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",
+                __LINE__, inN, outN);
+        return outVector;
+    }
+
+    if (outVector->type.type != PS_TYPE_U32) {
+        psError(__func__, " : Line %d - Output vector is not of type U32: out=%d\n",
+                __LINE__, outVector->type.type);
+        return outVector;
+    }
+
+    tmpVector = psVectorAlloc(inN, inType);
+    tmpVector->n = inN;
+    tmpVector = psVectorSort(tmpVector, inVector);
+
+    // Sort output vector
+    switch (inType) {
+    case PS_TYPE_U8:
+        SORT_INDICES(U8);
+        break;
+    case PS_TYPE_U16:
+        SORT_INDICES(U16);
+        break;
+    case PS_TYPE_U32:
+        SORT_INDICES(U32);
+        break;
+    case PS_TYPE_U64:
+        SORT_INDICES(U64);
+        break;
+    case PS_TYPE_S8:
+        SORT_INDICES(S8);
+        break;
+    case PS_TYPE_S16:
+        SORT_INDICES(S16);
+        break;
+    case PS_TYPE_S32:
+        SORT_INDICES(S32);
+        break;
+    case PS_TYPE_S64:
+        SORT_INDICES(S64);
+        break;
+    case PS_TYPE_F32:
+        SORT_INDICES(F32);
+        break;
+    case PS_TYPE_F64:
+        SORT_INDICES(F64);
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
+    }
+
+    // Free temp memory
+    psFree(tmpVector);
+
+    return outVector;
+}
+
+static void vectorFree(psVector* restrict psVec)
+{
+    if (psVec == NULL) {
+        return;
+    }
+
+    psFree(psVec->data.V);
+}
Index: /tags/rel2_1/psLib/src/collections/psVector.h
===================================================================
--- /tags/rel2_1/psLib/src/collections/psVector.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/collections/psVector.h	(revision 1553)
@@ -0,0 +1,133 @@
+
+/** @file  psVector.h
+ *
+ *  @brief Contains basic vector definitions and operations
+ *
+ *  This file defines the basic type for a vector struct and functions useful
+ *  in manupulating vectors.
+ *
+ *  @ingroup Vector
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:17:35 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_VECTOR_H
+#define PS_VECTOR_H
+
+#include "psType.h"
+
+/// @addtogroup Vector
+/// @{
+
+/** An vector to support primitive types.
+ *
+ * Struct for maintaining an vector of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psType type;                ///< Type of data.
+    unsigned int nalloc;        ///< Total number of elements available.
+    unsigned int n;             ///< Number of elements in use.
+
+    union {
+        psU8* U8;               ///< Unsigned 8-bit integer data.
+        psU16* U16;             ///< Unsigned 16-bit integer data.
+        psU32* U32;             ///< Unsigned 32-bit integer data.
+        psU64* U64;             ///< Unsigned 64-bit integer data.
+        psS8* S8;               ///< Signed 8-bit integer data.
+        psS16* S16;             ///< Signed 16-bit integer data.
+        psS32* S32;             ///< Signed 32-bit integer data.
+        psS64* S64;             ///< Signed 64-bit integer data.
+        psF32* F32;             ///< Single-precision float data.
+        psF64* F64;             ///< Double-precision float data.
+        psC32* C32;             ///< Single-precision complex data.
+        psC64* C64;             ///< Double-precision complex data.
+        psPTR V;                ///< Pointer to data.
+    } data;                     ///< Union for data types.
+}
+psVector;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a vector.
+ *
+ *  Uses psLib memory allocation functions to create a vector collection of 
+ *  data as defined by the psType type.
+ *
+ * @return psVector*    Pointer to psVector.
+ */
+psVector* psVectorAlloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psElemType dataType                ///< Type of data to be held by vector.
+);
+
+/** Reallocate a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection 
+ *  of data. The vector is reallocated according to the psType type member 
+ *  contained within the vector.
+ *
+ *  @return psVector*      Pointer to psVector.
+ *
+ */
+psVector* psVectorRealloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psVector* restrict psVec           ///< Vector to reallocate.
+);
+
+/** Recycle a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection 
+ *  of data. The vector is reallocated according to the psElemType type 
+ *  parameter.
+ *
+ * @return psVector*       Pointer to psVector.
+ *
+ */
+psVector* psVectorRecycle(
+    psVector* restrict psVec,
+    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
+    ///< taken to preserve the values.
+
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psElemType type                    ///< the datatype of the returned vector
+);
+
+/** Sort an array of floats.
+ *
+ *  Sorts an array of floats in ascending order.  This function is valid for
+ *  all non-complex data types.
+ *
+ *  @return  psVector*     Pointer to sorted psVector.
+ */
+psVector* psVectorSort(
+    psVector* restrict outVector,      ///< the output vector to recycle, or NULL if new vector desired.
+    const psVector* restrict inVector  ///< the vector to sort.
+);
+
+/** Creates an array of indices based on sort ordered of array.
+ *
+ *  Sorts a vector and creates an integer array holding indices of 
+ *  sorted float values based on pre-sort index positions.  
+ *
+ *  @return  psVector*     vector of the indices of sort.
+ */
+psVector* psVectorSortIndex(
+    psVector* restrict outVector,      ///< vector to recycle
+    const psVector* restrict inVector  ///< vector to sort
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/.cvsignore	(revision 1553)
@@ -0,0 +1,1 @@
+*.i
Index: /tags/rel2_1/psLib/src/dataManip/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/Makefile	(revision 1553)
@@ -0,0 +1,60 @@
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+TARGET_STATIC  = libpslib.a
+include ../Makefile.Globals
+CFLAGS := $(CFLAGS_RELOC) -I. -I../sysUtils -I../collections -I.. -I../image
+
+SRC_OBJS = psStats.o  \
+           psFunctions.o \
+           psMatrix.o \
+           psMatrixVectorArithmetic.o \
+           psFFT.o \
+           psMinimize.o \
+ 
+OBJS = $(addprefix makedir/,$(SRC_OBJS))
+          
+all: $(TARGET_STATIC)
+
+# force the creation of a psImage.i for psImage.o (to expand macros).
+psMatrixVectorArithmetic.o: psMatrixVectorArithmetic.i
+
+# Rule to make static library
+
+libpslib.a:     $(OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs ../$@ $(OBJS)
+
+# Define PHONY target "install" which will install necessary files
+install: $(TARGET_STATIC)
+	install *.h $(includedir)
+
+# Define PHONY target "distclean" which will cleanup the distribution
+distclean:      clean
+	$(RM) ../$(TARGET_STATIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+clean:
+	@echo "    Deleting intermediate files for 'sysUtils'"
+	$(RM) $(OBJS) *.lint $(SRC_OBJS:.o=.i)
+
+cleandep:
+	$(RM) $(OBJS:.o=.d)
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+%.i: %.c
+	$(CC) -E $(CFLAGS) -o $@ $<
+
+makedir/%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+makedir/%.d: %.c
+	$(CC) -MM $(CFLAGS) $< > $@.tmp
+	sed 's|\($*\)\.o[ :]*|\1.o $@ : |g' $@.tmp > $@
+	$(RM) -f $@.tmp
+
+include $(OBJS:.o=.d)
Index: /tags/rel2_1/psLib/src/dataManip/psFFT.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psFFT.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psFFT.c	(revision 1553)
@@ -0,0 +1,741 @@
+
+/** @file  psFFT.c
+*
+*  @brief Contains FFT transforms functions
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 18:54:38 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <complex.h>
+#include <fftw3.h>
+
+#include "psFFT.h"
+#include "psError.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psImageExtraction.h"
+
+#define P_FFTW_PLAN_RIGOR FFTW_ESTIMATE
+
+static bool p_fftwWisdomImported = false;
+
+psImage* psImageFFT(psImage* out, const psImage* in, psFftDirection direction)
+{
+    unsigned int numCols;
+    unsigned int numRows;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_C32 && direction == PS_FFT_REVERSE) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if (type != PS_TYPE_F32 && direction == PS_FFT_FORWARD) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    out = psImageCopy(out, in, PS_TYPE_C32);
+
+    plan = fftwf_plan_dft_2d(numCols, numRows,
+                             (fftwf_complex *) out->data.C32[0],
+                             (fftwf_complex *) out->data.C32[0], direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+
+}
+
+psImage* psImageReal(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just an image copy was performed.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageImaginary(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zero image was returned.");
+        out = psImageRecycle(out, numCols, numRows, type);
+        memset(out->data.V[0], 0, PSELEMTYPE_SIZEOF(type) * numCols * numRows);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageComplex(psImage* out, const psImage* real, const psImage* imag)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    numCols = real->numCols;
+    numRows = real->numRows;
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psImageComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (imag->numCols != numCols || imag->numRows != numRows) {
+        psError(__func__, "The inputs to psImageComplex must be the same dimensions.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psImageComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_F32 && type != PS_TYPE_F64) {
+        psError(__func__, "The input type to psImageComplex must be a floating point.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outRow;
+        psF32* realRow;
+        psF32* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            realRow = real->data.F32[row];
+            imagRow = imag->data.F32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else if (type == PS_TYPE_F64) {
+        psC64* outRow;
+        psF64* realRow;
+        psF64* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            realRow = real->data.F64[row];
+            imagRow = imag->data.F64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageConjugate(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Image copy was performed instead.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]) - I * cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psC64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]) - I * cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImagePowerSpectrum(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+    int numElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+    numElementsSquared = numCols * numCols * numRows * numRows;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+        psF32 real;
+        psF32 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = (real * real + imag * imag) / numElementsSquared;
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+        psF64 real;
+        psF64 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = real * real + imag * imag / numElementsSquared;
+            }
+        }
+    } else {
+        psError(__func__, "Can not power spectrum for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
+
+/************************************** Vector Functions ***************************************/
+
+psVector* psVectorFFT(psVector* out, const psVector* in, psFftDirection direction)
+{
+    unsigned int numElements;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if ((type != PS_TYPE_C32) && (direction == PS_FFT_REVERSE)) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if ((type != PS_TYPE_F32) && (direction == PS_FFT_FORWARD)) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numElements = in->n;
+
+    out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+    out->n = numElements;
+
+    if (type == PS_TYPE_F32) {
+        // need to convert to complex
+        psC32* outVec = out->data.C32;
+        psF32* inVec = in->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    } else {
+        psC32* outVec = out->data.C32;
+        psC32* inVec = in->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    }
+
+    plan = fftwf_plan_dft_1d(numElements,
+                             (fftwf_complex *) out->data.C32,
+                             (fftwf_complex *) out->data.C32, direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+}
+
+psVector* psVectorReal(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just a vector copy was performed.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, numElements * PSELEMTYPE_SIZEOF(type));
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorImaginary(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zeroed vector was returned.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memset(out->data.V, 0, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorComplex(psVector* out, const psVector* real, const psVector* imag)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    if (real->n < imag->n) {
+        numElements = real->n;
+    } else {
+        numElements = imag->n;
+    }
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psVectorComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psVectorComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outVec;
+        psF32* realVec = real->data.F32;
+        psF32* imagVec = imag->data.F32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = realVec[i] + I * imagVec[i];
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorConjugate(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Vector copy was performed instead.");
+
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]) - I * cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorPowerSpectrum(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int outNumElements;
+    unsigned int inNumElements;
+    unsigned int inHalfNumElements;
+    unsigned int inNumElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    inNumElements = in->n;
+    inNumElementsSquared = inNumElements * inNumElements;
+    inHalfNumElements = inNumElements / 2;
+    outNumElements = inHalfNumElements + 1;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+        psF32 inAbs1;
+        psF32 inAbs2;
+
+        out = psVectorRecycle(out, outNumElements, PS_TYPE_F32);
+        out->n = outNumElements;
+        outVec = out->data.F32;
+
+        // from ADD: P_0 = |C_0|^2/N^2
+        inAbs1 = cabsf(inVec[0]);
+        outVec[0] = inAbs1 * inAbs1 / inNumElementsSquared;
+
+        // from ADD: P_j = (|C_j|^2+|C_N-j|^2)/N^2, where j = 1,2,...,(N/2-1)
+        for (unsigned int i = 1; i < inHalfNumElements; i++) {
+            inAbs1 = cabsf(inVec[i]);
+            inAbs2 = cabsf(inVec[inNumElements - i]);
+            outVec[i] = (inAbs1 * inAbs1 + inAbs2 * inAbs2) / inNumElementsSquared;
+        }
+
+        // from ADD: P_N/2 = |C_N/2|^2/N^2
+        inAbs1 = cabsf(inVec[inHalfNumElements]);
+        outVec[inHalfNumElements] = inAbs1 * inAbs1 / inNumElementsSquared;
+    } else {
+        psError(__func__, "Can not power spectrum for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
Index: /tags/rel2_1/psLib/src/dataManip/psFFT.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psFFT.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psFFT.h	(revision 1553)
@@ -0,0 +1,158 @@
+
+/** @file  psFFT.h
+ *
+ *  @brief Contains FFT transforms functions
+ *
+ *  @ingroup Transform
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 18:54:38 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FFT_H
+#define PS_FFT_H
+
+#include "psImage.h"
+#include "psVector.h"
+
+/// @addtogroup Transform
+/// @{
+
+/** Specify direction of FFT */
+typedef enum {
+    /// psImageFFT/psVectorFFT should perform a forward FFT.
+    PS_FFT_FORWARD = (-1),
+
+    /// psImageFFT/psVectorFFT should perform a reverse FFT.
+    PS_FFT_REVERSE = (+1)
+} psFftDirection;
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the image of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input image may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psImage* the FFT transformation result
+ */
+psImage* psImageFFT(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in,                 ///< the psImage to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex image
+ * 
+ *  @return psImage*   real portion of the input image.
+ */
+psImage* psImageReal(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract real portion from
+);
+
+/** extract the imaginary portion of a complex image
+ * 
+ *  @return psImage*   imaginary portion of the input image.
+ */
+psImage* psImageImaginary(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract imaginary portion from
+);
+
+/** creates a complex image from separate real and imaginary plane images
+ * 
+ *  @return psImage*   resulting complex image
+ */
+psImage* psImageComplex(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* real,               ///< the real plane image
+    const psImage* imag                ///< the imaginary plane image
+);
+
+/** computes the complex conjugate of an image
+ * 
+ *  @return psImage*   the complex conjugate of the 'in' image
+ */
+psImage* psImageConjugate(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to compute conjugate of
+);
+
+/** computes the power spectrum of an image
+ * 
+ *  @return psImage*   the power spectrum of the 'in' image
+ */
+psImage* psImagePowerSpectrum(
+    psImage* out,                       ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                   ///< the psImage to power spectrum of
+);
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the vector of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input vector may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psVector* the FFT transformation result
+ */
+psVector* psVectorFFT(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in,                ///< the vector to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex vector
+ * 
+ *  @return psVector*   real portion of the input vector.
+ */
+psVector* psVectorReal(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                ///< the psVector to extract real portion from
+);
+
+/** extract the imaginary portion of a complex vector
+ * 
+ *  @return psVector*   imaginary portion of the input vector.
+ */
+psVector* psVectorImaginary(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to extract imaginary portion from
+);
+
+/** creates a complex vector from separate real and imaginary vectors
+ * 
+ *  @return psVector*   resulting complex vector
+ */
+psVector* psVectorComplex(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* real,              ///< the real vector
+    const psVector* imag               ///< the imaginary vector
+);
+
+/** computes the complex conjugate of a vector
+ * 
+ *  @return psVector*   the complex conjugate of the 'in' vector
+ */
+psVector* psVectorConjugate(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to compute conjugate of
+);
+
+/** computes the power spectrum of a vector
+ * 
+ *  @return psVector*   the power spectrum of the 'in' vector
+ */
+psVector* psVectorPowerSpectrum(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to power spectrum of
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psFunctions.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psFunctions.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psFunctions.c	(revision 1553)
@@ -0,0 +1,770 @@
+
+/** @file  psFunctions.c
+ *
+ *  @brief Contains basic function allocation, deallocation, and evaluation
+ *         routines.
+ *
+ *  This file will hold the functions for allocated, freeing, and evaluating
+ *  polynomials.  It also contains a Gaussian functions.
+ *
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:07:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************/
+
+/*  INCLUDE FILES                                                            */
+
+/*****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psFunctions.h"
+
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+static void polynomial1DFree(psPolynomial1D* myPoly);
+static void polynomial2DFree(psPolynomial2D* myPoly);
+static void polynomial3DFree(psPolynomial3D* myPoly);
+static void polynomial4DFree(psPolynomial4D* myPoly);
+static void dPolynomial1DFree(psDPolynomial1D* myPoly);
+static void dPolynomial2DFree(psDPolynomial2D* myPoly);
+static void dPolynomial3DFree(psDPolynomial3D* myPoly);
+static void dPolynomial4DFree(psDPolynomial4D* myPoly);
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - PUBLIC                                         */
+
+/*****************************************************************************/
+
+/*****************************************************************************
+    Evaluate a non-normalized Gaussian with the given mean and sigma at the
+    given coordianate.  Note that this is not a Gaussian deviate.  The
+    evaluated Gaussian is: \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
+ *****************************************************************************/
+float psGaussian(float x, float mean, float sigma, bool normal)
+{
+    float tmp = 1.0;
+
+    if (normal == true) {
+        #ifdef DARWIN
+        tmp = 1.0 / (float)sqrt(2.0 * M_PI * (sigma * sigma));
+        #else
+
+        tmp = 1.0 / sqrtf(2.0 * M_PI * (sigma * sigma));
+        #endif
+
+    }
+
+    return (tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma)));
+}
+
+/*****************************************************************************
+    psGaussianDev()
+ This routine creates a psVector of the specified size and type F32
+ and fills it with a random Gaussian distribution of numbers with
+ the specified mean and sigma.  This routine makes use of the GSL
+ routines for generating both uniformly distributed numbers and the
+ Gaussian distribution as well.
+ 
+ NOTE: There is no way to seed the random generator.
+ *****************************************************************************/
+psVector* psGaussianDev(float mean, float sigma, int Npts)
+{
+    psVector* gauss = NULL;
+    const gsl_rng_type *T = NULL;
+    gsl_rng *r = NULL;
+    int i = 0;
+
+    gauss = psVectorAlloc(Npts, PS_TYPE_F32);
+    gauss->n = Npts;
+    gsl_rng_env_setup();
+    T = gsl_rng_default;
+    r = gsl_rng_alloc(T);
+
+    for (i = 0; i < Npts; i++) {
+        gauss->data.F32[i] = mean + gsl_ran_gaussian(r, sigma);
+    }
+
+    // NOTE: Should I free r as well?
+    return (gauss);
+}
+
+/*****************************************************************************
+    This routine must allocate memory for the polynomial structures.
+ *****************************************************************************/
+psPolynomial1D* psPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psPolynomial1D* newPoly = NULL;
+
+    newPoly = (psPolynomial1D* ) psAlloc(sizeof(psPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (float *)psAlloc(n * sizeof(float));
+    newPoly->coeffErr = (float *)psAlloc(n * sizeof(float));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psPolynomial2D* psPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psPolynomial2D* newPoly = NULL;
+
+    newPoly = (psPolynomial2D* ) psAlloc(sizeof(psPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->coeffErr = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->coeffErr[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial3D* psPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial3D* newPoly = NULL;
+
+    newPoly = (psPolynomial3D* ) psAlloc(sizeof(psPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->coeffErr = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->coeffErr[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->coeffErr[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial4D* psPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial4D* newPoly = NULL;
+
+    newPoly = (psPolynomial4D* ) psAlloc(sizeof(psPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->coeffErr = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->coeffErr[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->coeffErr[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->coeffErr[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void polynomial1DFree(psPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial2DFree(psPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial3DFree(psPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial4DFree(psPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ 
+    XXX: Determine, from IfA, whether ot not the "mask[]" terms should be used
+    in polynomial evaluation.  If so, then all of the following polynomial
+    evaluation functions must be modified to do so.
+ 
+    XXX: Should the "coeffErr[]" should be used as well?
+ *****************************************************************************/
+float psPolynomial1DEval(float x, const psPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+
+    if (NULL == myPoly) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly is NULL\n");
+    }
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    if (NULL == myPoly->coeff) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly->coeff is NULL\n");
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial2DEval(float x, float y, const psPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial3DEval(float x, float y, float z, const psPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial4DEval(float w, float x, float y, float z, const psPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float wSum = 1.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
+
+psDPolynomial1D* psDPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psDPolynomial1D* newPoly = NULL;
+
+    newPoly = (psDPolynomial1D* ) psAlloc(sizeof(psDPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (double *)psAlloc(n * sizeof(double));
+    newPoly->coeffErr = (double *)psAlloc(n * sizeof(double));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial2D* psDPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psDPolynomial2D* newPoly = NULL;
+
+    newPoly = (psDPolynomial2D* ) psAlloc(sizeof(psDPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->coeffErr = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->coeffErr[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial3D* psDPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial3D* newPoly = NULL;
+
+    newPoly = (psDPolynomial3D* ) psAlloc(sizeof(psDPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->coeffErr = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->coeffErr[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->coeffErr[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial4D* psDPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial4D* newPoly = NULL;
+
+    newPoly = (psDPolynomial4D* ) psAlloc(sizeof(psDPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->coeffErr = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->coeffErr[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->coeffErr[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->coeffErr[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void dPolynomial1DFree(psDPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial2DFree(psDPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial3DFree(psDPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial4DFree(psDPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ *****************************************************************************/
+double psDPolynomial1DEval(double x, const psDPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial2DEval(double x, double y, const psDPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial3DEval(double x, double y, double z, const psDPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial4DEval(double w, double x, double y, double z, const psDPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double wSum = 1.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
Index: /tags/rel2_1/psLib/src/dataManip/psFunctions.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psFunctions.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psFunctions.h	(revision 1553)
@@ -0,0 +1,318 @@
+
+/** @file psFunctions.h
+*  \brief Standard Mathematical Functions.
+*  \ingroup Stats
+*
+*  This file will hold the prototypes for procedures which allocate, free,
+*  and evaluate various polynomials.  Those polynomial structures are also
+*  defined here.
+*
+*  @ingroup Stats
+*
+*  @author Someone at IfA
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-11 02:35:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#if !defined(PS_FUNCTIONS_H)
+#define PS_FUNCTIONS_H
+
+#include <stdbool.h>
+
+#include "psVector.h"
+
+/** \addtogroup Stats
+ *  \{
+ */
+
+/** Evaluate a non-normalized Gaussian with the given mean and sigma at the
+ *  given coordianate.  
+ *
+ *  Note that this is not a Gaussian deviate.  The evaluated Gaussian is: 
+ *        \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f] 
+ *
+ *  @return float      value on the gaussian curve given the input parameters
+ */
+float psGaussian(
+    float x,                           ///< Value at which to evaluate
+    float mean,                        ///< Mean for the Gaussian
+    float stddev,                      ///< Standard deviation for the Gaussian
+    bool normal                        ///< Indicates whether result should be normalized
+);
+
+/** Produce a vector of random numbers from a Gaussian distribution with
+ *  the specified mean and sigma 
+ *  
+ *  @return psVector*    vector of random numbers
+ *  
+ */
+psVector* psGaussianDev(
+    float mean,                        ///< The mean of the Gaussian
+    float sigma,                       ///< The sigma of the Gaussian
+    int Npts                           ///< The size of the vector
+);
+
+/** One-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    float *coeff;                      ///< Coefficients
+    float *coeffErr;                   ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psPolynomial1D;
+
+/** Two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    float **coeff;                     ///< Coefficients
+    float **coeffErr;                  ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psPolynomial2D;
+
+/** Three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ***coeff;                    ///< Coefficients
+    float ***coeffErr;                 ///< Error in coefficients
+    char ***mask;                      ///< Coefficients mask
+}
+psPolynomial3D;
+
+/** Four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ****coeff;                   ///< Coefficients
+    float ****coeffErr;                ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psPolynomial4D;
+
+
+/** Allocates a psPolynomial1D structure with n terms
+ *
+ *  @return  psPolynomial1D*    new 1-D polynomial struct
+ */
+psPolynomial1D* psPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new 2-D polynomial struct
+ */
+psPolynomial2D* psPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new 3-D polynomial struct
+ */
+psPolynomial3D* psPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new 4-D polynomial struct
+ */
+psPolynomial4D* psPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial1DEval(
+    float x,                           ///< location at which to evaluate
+    const psPolynomial1D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial2DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    const psPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial3DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial3D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial4DEval(
+    float w,                           ///< w location at which to evaluate
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial4D* myPoly       ///< Coefficients for the polynomial
+);
+
+/*****************************************************************************/
+
+/* Double-precision polynomials, mainly for use in astrometry */
+
+/** Double-precision one-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    double *coeff;                     ///< Coefficients
+    double *coeffErr;                  ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psDPolynomial1D;
+
+/** Double-precision two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    double **coeff;                    ///< Coefficients
+    double **coeffErr;                 ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psDPolynomial2D;
+
+/** Double-precision three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ***coeff;                   ///< Coefficients
+    double ***coeffErr;                ///< Error in coefficients
+    char ***mask;                      ///< Coefficient mask
+}
+psDPolynomial3D;
+
+/** Double-precision four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ****coeff;                  ///< Coefficients
+    double ****coeffErr;               ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psDPolynomial4D;
+
+/** Allocates a double-precision 1-D polynomial structure with n terms
+ *
+ *  @return  psPolynomial1D*    new double-precision 1-D polynomial struct
+ */
+psDPolynomial1D* psDPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a double-precision 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new double-precision 2-D polynomial struct
+ */
+psDPolynomial2D* psDPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a double-precision 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new double-precision 3-D polynomial struct
+ */
+psDPolynomial3D* psDPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a double-precision 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new double-precision 4-D polynomial struct
+ */
+psDPolynomial4D* psDPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a double-precision 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial1DEval(
+    double x,                          ///< Value at which to evaluate
+    const psDPolynomial1D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial2DEval(
+    double x,                           ///< Value x at which to evaluate
+    double y,                           ///< Value y at which to evaluate
+    const psDPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial3DEval(
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial3D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial4DEval(
+    double w,                          ///< Value w at which to evaluate
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial4D* myPoly      ///< Coefficients for the polynomial
+);
+
+/* \} */// End of MathGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psMatrix.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMatrix.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMatrix.c	(revision 1553)
@@ -0,0 +1,582 @@
+
+/** @file  psMatrix.c
+ *
+ *  @brief Provides functions for linear algebra operations on psImages and psVectors. 
+ *
+ *  Functions are provided to:
+ *      Transpose a psImage
+ *      Compute LUD
+ *      Solve LUD
+ *      Matrix inversion
+ *      Calculate determinant
+ *      Matrix addition
+ *      Matrix subtraction
+ *      Matrix multiplication
+ *      Calculate Eigenvectors
+ *      Convert matrix to vector
+ *      Convert vector to matrix
+ *
+ *  These functions treat psImages as if they were matrices, therefore there is no psMatrix.
+ *
+ *  @author Ross Harman, MHPCC
+ *   
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_linalg.h>
+#include <gsl/gsl_permutation.h>
+#include <gsl/gsl_eigen.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psMatrix.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+/** Preprocessor macro to generate error a NULL image */
+#define PS_CHECK_NULL_VECTOR(NAME, RETURN)                                                          \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to create vector based on another */
+#define PS_CHECK_ALLOC_VECTOR(NAME, SIZE, PS_TYPE)                                                  \
+if(NAME == NULL) {                                                                                  \
+    NAME = psVectorAlloc(SIZE, PS_TYPE);                                                            \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_SIZE_VECTOR(NAME, RETURN)                                                          \
+if (NAME->n < 1) {                                                                                  \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to generate error a NULL image */
+#define PS_CHECK_NULL_IMAGE(NAME, RETURN)                                                           \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to create image based on another */
+#define PS_CHECK_ALLOC_IMAGE(NAME, NCOLS, NROWS, PS_TYPE)                                           \
+if(NAME == NULL) {                                                                                  \
+    NAME = psImageAlloc(NCOLS, NROWS, PS_TYPE);                                                     \
+}
+
+/** Preprocessor macro to generate error for zero length rows or columns */
+#define PS_CHECK_SIZE_IMAGE(NAME, RETURN)                                                           \
+if (NAME->numCols < 1 || NAME->numRows < 1) {                                                       \
+    psError(__func__,"Invalid operation: %s has zero rows or columns (%dx%d).", #NAME,              \
+            NAME->numCols, NAME->numRows);                                                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to generate error for image dimensionality not set to PS_DIMEN_IMAGE */
+#define PS_CHECK_DIMEN_AND_TYPE(NAME, PS_DIMEN, RETURN)                                             \
+if (NAME->type.dimen != PS_DIMEN) {                                                                 \
+    psError(__func__,"Invalid operation: %s incorrect dimensionality %d.", #NAME, PS_DIMEN);        \
+    return RETURN;                                                                                  \
+} else if(NAME->type.type != PS_TYPE_F64) {                                                         \
+    psError(__func__, "Invalid operation: %s not PS_TYPE_F64.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to check that input is not equal to output */
+#define PS_CHECK_POINTERS(NAME1, NAME2, RETURN)                                                     \
+if (NAME1 == NAME2) {                                                                               \
+    psError(__func__,"Invalid operation: Pointer to %s is same as %s.", #NAME1, #NAME2);            \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to check that an image is square */
+#define PS_CHECK_SQUARE(NAME, RETURN)                                                               \
+if (NAME->numCols != NAME->numRows) {                                                               \
+    psError(__func__,"Invalid operation: %s not square array.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to initalize a GSL matrix. */
+#define PS_GSL_MATRIX_INITIALIZE(LHS_NAME, RHS_NAME)                                                \
+LHS_NAME.size1 = numRows;                                                                           \
+LHS_NAME.size2 = numCols;                                                                           \
+LHS_NAME.tda   = numCols;                                                                           \
+LHS_NAME.data  = RHS_NAME;
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psImage* psMatrixLUD(psImage* outImage, psVector* outPerm, psImage* inImage)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix lu;
+    gsl_permutation perm;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+    PS_CHECK_ALLOC_VECTOR(outPerm, inImage->numRows, inImage->type.type);
+    PS_CHECK_NULL_VECTOR(outPerm, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(outPerm, PS_DIMEN_VECTOR, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    perm.size = numCols;
+    outPerm->n = numCols;
+    perm.data = outPerm->data.V;
+    PS_GSL_MATRIX_INITIALIZE(lu, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu.data, inImage->data.V[0], arraySize);
+
+    // Calculate LU decomposition
+    gsl_linalg_LU_decomp(&lu, &perm, &signum);
+
+    return outImage;
+}
+
+psVector* psMatrixLUSolve(psVector* outVector, const psImage* inImage, const psVector* inVector, const
+                          psVector* inPerm)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix lu;
+    gsl_permutation perm;
+    gsl_vector b;
+    gsl_vector x;
+
+    // Error checks
+    PS_CHECK_POINTERS(outVector, inVector, outVector);
+    PS_CHECK_POINTERS(inVector, inPerm, outVector);
+    PS_CHECK_POINTERS(outVector, inPerm, outVector);
+    PS_CHECK_NULL_IMAGE(inImage, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outVector);
+    PS_CHECK_SIZE_IMAGE(inImage, outVector);
+    PS_CHECK_ALLOC_VECTOR(outVector, inImage->numRows, inImage->type.type);
+    PS_CHECK_NULL_VECTOR(outVector, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_VECTOR, outVector);
+    PS_CHECK_NULL_VECTOR(inVector, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_VECTOR, outVector);
+    PS_CHECK_NULL_VECTOR(inPerm, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inPerm, PS_DIMEN_VECTOR, outVector);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(lu, inImage->data.V[0]);
+
+    outVector->n = numCols;
+
+    perm.size = inPerm->n;
+    perm.data = inPerm->data.V;
+
+    b.size = inVector->n;
+    b.stride = 1;
+    b.data = inVector->data.V;
+
+    x.size = numCols;
+    x.stride = 1;
+    x.data = outVector->data.V;
+
+    // Solve for {x} in equation: {b} = [A]{x}
+    gsl_linalg_LU_solve(&lu, &perm, &b, &x);
+
+    return outVector;
+}
+
+psImage* psMatrixInvert(psImage* outImage, const psImage* inImage, float *restrict det)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix inv;
+    gsl_matrix *lu;
+    gsl_permutation *perm = NULL;
+
+    // Error checks
+    if (det == NULL) {
+        psError(__func__, "Invalid operation: determinant argument is NULL.");
+        return outImage;
+    }
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Allocate GSL structs
+    perm = gsl_permutation_alloc(inImage->numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(inv, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu->data, inImage->data.V[0], arraySize);
+
+    // Invert data and calculate determinant
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    gsl_linalg_LU_invert(lu, perm, &inv);
+    *det = (float)gsl_linalg_LU_det(lu, signum);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+
+    return outImage;
+}
+
+float *psMatrixDeterminant(const psImage* restrict inImage)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    float *det = NULL;
+    gsl_matrix *lu = NULL;
+    gsl_permutation *perm = NULL;
+
+    // Error checks
+    PS_CHECK_NULL_IMAGE(inImage, NULL);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, NULL);
+    PS_CHECK_SIZE_IMAGE(inImage, NULL);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Allocate GSL structs
+    perm = gsl_permutation_alloc(numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, 0);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu->data, inImage->data.V[0], arraySize);
+
+    // Calculate determinant
+    det = (float *)psAlloc(sizeof(float));
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    *det = (float)gsl_linalg_LU_det(lu, signum);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+
+    return det;
+}
+
+psImage* psMatrixMultiply(psImage* outImage, psImage* inImage1, psImage* inImage2)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix m1;
+    gsl_matrix m2;
+    gsl_matrix m3;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage1, outImage, outImage);
+    PS_CHECK_POINTERS(inImage1, inImage2, outImage);
+    PS_CHECK_NULL_IMAGE(inImage1, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage1, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage1, outImage);
+    PS_CHECK_NULL_IMAGE(inImage2, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage2, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage2, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage2->numCols, inImage2->numRows, inImage2->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(inImage1, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage1->numRows;
+    numCols = inImage1->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(outImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(m1, inImage1->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(m2, inImage2->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(m3, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage1, outImage);
+    PS_CHECK_SQUARE(inImage2, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    gsl_linalg_matmult(&m1, &m2, &m3);
+
+    return outImage;
+}
+
+psImage* psMatrixTranspose(psImage* outImage, const psImage* inImage)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix trans;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(trans, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into psImage output data to keep input data pristine
+    memcpy(outImage->data.V[0], inImage->data.V[0], arraySize);
+
+    // Transpose data
+    gsl_matrix_transpose(&trans);
+
+    return outImage;
+}
+
+psImage* psMatrixEigenvectors(psImage* outImage, psImage* inImage)
+{
+    int numRows = 0;
+    int numCols = 0;
+    gsl_vector *eVals = NULL;
+    gsl_eigen_symmv_workspace *w = NULL;
+    gsl_matrix out;
+    gsl_matrix in;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(in, inImage->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(out, outImage->data.V[0]);
+
+    // Allocate GSL structs
+    eVals = gsl_vector_alloc(numRows);
+    w = gsl_eigen_symmv_alloc(numRows);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Calculate Eigenvalues and Eigenvectors...Eigenvalues not currently used
+    gsl_eigen_symmv(&in, eVals, &out, w);
+
+    // Free GSL structs
+    gsl_eigen_symmv_free(w);
+    gsl_vector_free(eVals);
+
+    return outImage;
+}
+
+psVector* psMatrixToVector(psVector* outVector, psImage* inImage)
+{
+    int size = 0;
+
+    // Error checks
+    PS_CHECK_NULL_IMAGE(inImage, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outVector);
+    PS_CHECK_SIZE_IMAGE(inImage, outVector);
+
+    if (inImage->numRows == 1) {
+        // Create transposed row vector
+        PS_CHECK_ALLOC_VECTOR(outVector, inImage->numCols, inImage->type.type);
+        outVector->type.dimen = PS_DIMEN_TRANSV;
+    } else if (inImage->numCols == 1) {
+        // Create non-transposed column vector
+        PS_CHECK_ALLOC_VECTOR(outVector, inImage->numRows, inImage->type.type);
+    } else {
+        psError(__func__, "Image does not have dim with 1 col or 1 row: (%d x %d).", inImage->numRows,
+                inImage->numCols);
+        return outVector;
+    }
+
+    PS_CHECK_NULL_VECTOR(outVector, outVector);
+
+    // More checks
+    if (outVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_VECTOR, outVector);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numRows;
+        }
+
+        if (outVector->n != inImage->numRows) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numRows, outVector->n);
+            return outVector;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numRows;
+
+    } else if (outVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_TRANSV, outVector);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numCols;
+        }
+
+        if (outVector->n != inImage->numCols) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numCols, outVector->n);
+            return outVector;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numCols;
+    }
+
+    memcpy(outVector->data.V, inImage->data.V[0], size);
+
+    return outVector;
+}
+
+psImage* psVectorToMatrix(psImage* outImage, psVector* inVector)
+{
+    int size = 0;
+
+    // Error checks
+    PS_CHECK_NULL_VECTOR(inVector, outImage);
+
+    if (inVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_VECTOR, outImage);
+        PS_CHECK_SIZE_VECTOR(inVector, outImage);
+        PS_CHECK_ALLOC_IMAGE(outImage, 1, inVector->n, PS_TYPE_F64)
+        // More checks for PS_DIMEN_VECTOR
+        if (outImage->numCols > 1) {
+            psError(__func__, "Image has more than 1 column: numCols = %d.", outImage->numCols);
+            return outImage;
+        } else if (outImage->numRows != inVector->n) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numRows, inVector->n);
+            return outImage;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numRows;
+
+    } else if (inVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_TRANSV, outImage);
+        PS_CHECK_SIZE_VECTOR(inVector, outImage);
+        PS_CHECK_ALLOC_IMAGE(outImage, inVector->n, 1, PS_TYPE_F64)
+        // More checks for PS_DIMEN_TRANSV
+        if (outImage->numRows > 1) {
+            psError(__func__, "Image has more than 1 row: numRows = %d.", outImage->numRows);
+            return outImage;
+        } else if (outImage->numCols != inVector->n) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numCols, inVector->n);
+            return outImage;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numCols;
+    }
+
+    PS_CHECK_NULL_IMAGE(outImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+
+    memcpy(outImage->data.V[0], inVector->data.V, size);
+
+    return outImage;
+}
Index: /tags/rel2_1/psLib/src/dataManip/psMatrix.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMatrix.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMatrix.h	(revision 1553)
@@ -0,0 +1,166 @@
+
+/** @file  psMatrix.h
+ *
+ *  @brief Provides functions for linear algebra operations on psImages and psVectors. 
+ *
+ *  Functions are provided to:
+ *      Transpose a psImage
+ *      Compute LUD
+ *      Solve LUD
+ *      Matrix inversion
+ *      Calculate determinant
+ *      Matrix multiplication
+ *      Calculate Eigenvectors
+ *      Convert matrix to vector
+ *      Convert vector to matrix
+ *
+ *  These functions treat psImages as if they were matrices, therefore there is no psMatrix. These functions
+ *  operate only with the psF64 data type.
+ *
+ *  @ingroup Matrix
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 02:35:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSMATRIX_H
+#define PSMATRIX_H
+
+/// @addtogroup Matrix
+/// @{
+
+/** LU Decomposition of psImage matrix.
+ *
+ *  Performs a LU decomposition on a psImage matrix and returns the LU matrix. If the user specifies NULL for
+ *  the outImage or outPerm arguments, then they will be automatically created. The input image must 
+ *  be square. This function operates only with the psF64 data type. Input and output arguments should not be 
+ *  the same. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to LU decomposed psImage.
+ */
+psImage* psMatrixLUD(
+    psImage* outImage,                 ///< Image to return, or NULL.
+    psVector* outPerm,                 ///< Output permutation vector used by psMatrixLUSolve.
+    psImage* inImage                   ///< Image to decompose.
+);
+
+/** LU Solution of psImage matrix.
+ *
+ *  Solves for and returns the psVector, {x} in the equation [A]{x} = {b}. If the user specifies NULL as the 
+ *  outVector argument, then it will automatically be created. The input image must be square. This function 
+ *  operates only with the psF64 data type. Input and output arguments should not be the same. GSL indexes 
+ *  the top row as the zero row, not the bottom.  
+ *
+ *  @return  psVector* : Pointer to psVector solution of matrix equation.
+ */
+psVector* psMatrixLUSolve(
+    psVector* outVector,               ///< Vector to return, or NULL.
+    const psImage* luImage,            ///< LU-decomposed matrix.
+    const psVector* inVector,          ///< Vector right-hand-side of equation.
+    const psVector* inPerm             ///< Permutation vector resulting from psMatrixLUD function.
+);
+
+/** Invert psImage matrix.
+ *
+ *  Inverts a psImage matrix and returns the determinant as an option through the argument list. If the user
+ *  specifies NULL as the outImage argument, then it will automatically be created. The input image must be 
+ *  square. This function operates only with the psF64 data type. Input and output arguments should not be 
+ *  the same. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to inverted psImage.
+ */
+psImage* psMatrixInvert(
+    psImage* outImage,                 ///< Image to return, or NULL for in-place substitution.
+    const psImage* inImage,            ///< Image to be inverted
+    float *restrict det                ///< Determinant to return, or NULL
+);
+
+/** Calculate psImage matrix determinant.
+ *
+ *  Calculates the determinant of a psImage matrix and returns the single precision floating point result. The
+ *  input image must be square. This function operates only with the psF64 data type. GSL indexes the top row 
+ *  as the zero row, not the bottom.  
+ *
+ *  @return  float: Determinant from psImage.
+ */
+float *psMatrixDeterminant(
+    const psImage* restrict inMatrix   ///< Image used to calculate determinant.
+);
+
+/** Performs psImage matrix multiplication.
+ *
+ *  Performs a classical matrix multiplication involving row and column operations. Input images must be square 
+ *  and the same size. If the user specifies NULL as the outImage argument, then it will automatically be 
+ *  created. This function operates only with the psF64 data type. GSL indexes the top row as the
+ *  zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to resulting psImage.
+ */
+psImage* psMatrixMultiply(
+    psImage* outImage,                 ///< Matrix to return, or NULL.
+    psImage* inImage1,                 ///< First input image.
+    psImage* inImage2                  ///< Second input image.
+);
+
+/** Transpose matrix.
+ *
+ *  Performs psImage matrix transpose by substituting existing rows for columns. The input image must be 
+ *  square. If the user specifies NULL as the outImage argument, then it will automaticallty be created.
+ *  This function operates only with the psF64 data type. GSL indexes the top row as the zero 
+ *  row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to transposed psImage.
+ */
+psImage* psMatrixTranspose(
+    psImage* outImage,                 ///< Image to return, or NULL
+    const psImage* inImage             ///< Image to transpose
+);
+
+/** Calculate matrix eigenvectors.
+ *
+ *  Calculates the eigenvectors for a matrix. The input image must be symmetric and square. If the user 
+ *  specifies NULL as the outImage argument, then it will automatically be created. This function operates 
+ *  only with the psF64 data type. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to matrix of Eigenvectors.
+ */
+psImage* psMatrixEigenvectors(
+    psImage* outImage,                 ///< Eigenvectors to return, or NULL.
+    psImage* inImage                   ///< Input image.
+);
+
+/** Convert matrix to vector.
+ *
+ *  Converts a 1-d psImage matrix into a vector. If the user specifies NULL as the outVector argument, then it
+ *  will automatically be created based on the input image (PS_DIMEN_VECTOR for an input image with 1 col or
+ *  PS_DIMENT_TRANSV for an input image with 1 row). Either the number of rows or the number of colums of the
+ *  input matrix must be 1. This function operates only  with the psF64 data type.
+ *
+ *  @return  psVector* : Pointer to psVector.
+ */
+psVector* psMatrixToVector(
+    psVector* outVector,               ///< Vector to return, or NULL.
+    psImage* inImage                   ///< Image to convert.
+);
+
+/** Convert vector to matrix.
+ *
+ *  Converts a vector into a psImage matrix. If the dimensionality of the vector is PS_DIMEN_VECTOR, then the
+ *  resulting psImage is a 1d column. If the dimensionality of the vector is PS_DIMEN_TRANSV, then the
+ *  resulting psImage is a 1d row. If the user specifies NULL as the outImage argument,  then it will 
+ *  automatically be created. This function operates only with the psF64 data type.  
+ *
+ *  @return  psVector* : Pointer to psIamge.
+ */
+psImage* psVectorToMatrix(
+    psImage* outImage,                 ///< Matrix to return, or NULL.
+    psVector* inVector                 ///< Vector to convert.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.c	(revision 1553)
@@ -0,0 +1,794 @@
+
+/** @file  psMatrixVectorArithmetic.c
+ *
+ *  @brief Provides unary and binary functions for simple matrix and vector element operations. Functions
+ *  include:
+ *
+ *      Addition (+)
+ *      Subtraction (-)
+ *      Multiplication (*)
+ *      Division (/)
+ *      Power (^)
+ *      Minimum (min)
+ *      Maximum (max)
+ *      Absolute value (abs)
+ *      Exponent (exp)
+ *      Natural Log (ln)
+ *      Power of 10 (ten)
+ *      Log (log)
+ *      Sine (sin or dsin)
+ *      Cosine (cos or dcos)
+ *      Tangent (tan or dtan)
+ *      Arcsine (asin or dasin)
+ *      Arccosine (acos or dacos)
+ *      Arctan (atan or datan)
+ *
+ *  Currently only vector-vector and image-image binary operations are supported.
+ *
+ *  @ingroup MatrixVectorArithmetic
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-14 01:31:43 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psScalar.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// Conversion for degrees to radians
+#define D2R 0.01745329252111111  /* PI/180 */
+
+// Conversion for radians to degrees
+#define R2D 57.29577950924861   /* 180.0/PI */
+
+// Division with NAN checking
+static complex double psNanDiv(complex double a, complex double b)
+{
+    complex double out = 0 + 0i;
+
+    out = a / b;
+    if (isnan(creal(out)) || isnan(cimag(out))) {
+        psError(__func__, ": Divide by zero");
+    }
+
+    return out;
+}
+
+// Binary SCALAR_XXXX operations
+#define SCALAR_SCALAR(OUT,IN1,OP,IN2,TYPE)                                                                   \
+{                                                                                                            \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    o  = &((psScalar* )OUT)->data.TYPE;                                                                       \
+    i1 = &((psScalar* )IN1)->data.TYPE;                                                                       \
+    i2 = &((psScalar* )IN2)->data.TYPE;                                                                       \
+    *o = OP;                                                                                                 \
+}
+
+#define SCALAR_VECTOR(OUT,IN1,OP,IN2,TYPE)                                                                   \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int npt = 0;                                                                                             \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    npt  = ((psVector* )IN1)->n;                                                                              \
+    o  = ((psVector* )OUT)->data.TYPE;                                                                        \
+    i1 = &((psScalar* )IN1)->data.TYPE;                                                                       \
+    i2 = ((psVector* )IN2)->data.TYPE;                                                                        \
+    for (i=0; i < npt; i++, o++, i2++) {                                                                     \
+        *o = OP;                                                                                             \
+    }                                                                                                        \
+}
+
+#define SCALAR_IMAGE(OUT,IN1,OP,IN2,TYPE)                                                                    \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int numRows = 0;                                                                                         \
+    int numCols = 0;                                                                                         \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    numRows = ((psImage* )IN1)->numRows;                                                                      \
+    numCols = ((psImage* )IN1)->numCols;                                                                      \
+    for(j = 0; j < numCols; j++) {                                                                           \
+        o  = ((psImage* )OUT)->data.TYPE[j];                                                                  \
+        i1 = &((psScalar* )IN1)->data.TYPE;                                                                   \
+        i2 = ((psImage* )IN2)->data.TYPE[j];                                                                  \
+        for(i = 0; i < numRows; i++, o++, i2++) {                                                            \
+            *o = OP;                                                                                         \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+// Binary VECTOR_XXXX operations
+#define VECTOR_SCALAR(OUT,IN1,OP,IN2,TYPE)                                                                   \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int n1 = 0;                                                                                              \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    n1  = ((psVector* )IN1)->n;                                                                               \
+    o  = ((psVector* )OUT)->data.TYPE;                                                                        \
+    i1 = ((psVector* )IN1)->data.TYPE;                                                                        \
+    i2 = &((psScalar* )IN2)->data.TYPE;                                                                       \
+    for (i=0; i < n1; i++, o++, i1++) {                                                                      \
+        *o = OP;                                                                                             \
+    }                                                                                                        \
+}
+
+#define VECTOR_VECTOR(OUT,IN1,OP,IN2,TYPE)                                                                   \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int n1 = 0;                                                                                              \
+    int n2 = 0;                                                                                              \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    n1  = ((psVector* )IN1)->n;                                                                               \
+    n2  = ((psVector* )IN2)->n;                                                                               \
+    if(n1 != n2) {                                                                                           \
+        psError(__func__, ": Inconsistent element count: %d vs %d", n1, n2);                                 \
+        return OUT;                                                                                          \
+    }                                                                                                        \
+    o  = ((psVector* )OUT)->data.TYPE;                                                                        \
+    i1 = ((psVector* )IN1)->data.TYPE;                                                                        \
+    i2 = ((psVector* )IN2)->data.TYPE;                                                                        \
+    for (i=0; i < n1; i++, o++, i1++, i2++) {                                                                \
+        *o = OP;                                                                                             \
+    }                                                                                                        \
+}
+
+#define VECTOR_IMAGE(OUT,IN1,OP,IN2,TYPE)                                                                    \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int n1 = 0;                                                                                              \
+    int numRows2 = 0;                                                                                        \
+    int numCols2 = 0;                                                                                        \
+    psDimen dim1 = 0;                                                                                        \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    n1  = ((psVector* )IN1)->n;                                                                               \
+    dim1 = ((psVector* )IN1)->type.dimen;                                                                     \
+    numRows2 = ((psImage* )IN2)->numRows;                                                                     \
+    numCols2 = ((psImage* )IN2)->numCols;                                                                     \
+    \
+    if(dim1 == PS_DIMEN_VECTOR) { /* Regular vectors */                                                      \
+        if(n1!=numRows2) {                                                                                   \
+            psError(__func__, ": Inconsistent element count: %d vs %d", n1, numRows2);                       \
+            return OUT;                                                                                      \
+        }                                                                                                    \
+        \
+        i1 = ((psVector* )IN1)->data.TYPE;                                                                    \
+        for(j = 0; j < numRows2; j++, i1++) {                                                                \
+            o  = ((psImage* )OUT)->data.TYPE[j];                                                              \
+            i2 = ((psImage* )IN2)->data.TYPE[j];                                                              \
+            for(i = 0; i < numCols2; i++, o++, i2++) {                                                       \
+                *o = OP;                                                                                     \
+            }                                                                                                \
+        }                                                                                                    \
+    } else {  /* Transposed vectors */                                                                       \
+        if(n1!=numCols2) {                                                                                   \
+            psError(__func__, ": Inconsistent element count: %d vs %d", n1, numCols2);                       \
+            return OUT;                                                                                      \
+        }                                                                                                    \
+        \
+        for(j = 0; j < numRows2; j++) {                                                                      \
+            o  = ((psImage* )OUT)->data.TYPE[j];                                                              \
+            i1 = ((psVector* )IN1)->data.TYPE;                                                                \
+            i2 = ((psImage* )IN2)->data.TYPE[j];                                                              \
+            for(i = 0; i < numCols2; i++, o++, i1++, i2++) {                                                 \
+                *o = OP;                                                                                     \
+            }                                                                                                \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+// Binary IMAGE_XXXX operations
+#define IMAGE_SCALAR(OUT,IN1,OP,IN2,TYPE)                                                                    \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int numRows = 0;                                                                                         \
+    int numCols = 0;                                                                                         \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    numRows = ((psImage* )IN1)->numRows;                                                                      \
+    numCols = ((psImage* )IN1)->numCols;                                                                      \
+    for(j = 0; j < numRows; j++) {                                                                           \
+        o  = ((psImage* )OUT)->data.TYPE[j];                                                                  \
+        i1 = ((psImage* )IN1)->data.TYPE[j];                                                                  \
+        i2 = &((psScalar* )IN2)->data.TYPE;                                                                   \
+        for(i = 0; i < numCols; i++, o++, i1++) {                                                            \
+            *o = OP;                                                                                         \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+#define IMAGE_VECTOR(OUT,IN1,OP,IN2,TYPE)                                                                    \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int n2 = 0;                                                                                              \
+    int numRows1 = 0;                                                                                        \
+    int numCols1 = 0;                                                                                        \
+    psDimen dim2 = 0;                                                                                        \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    n2  = ((psVector* )IN2)->n;                                                                               \
+    dim2 = ((psVector* )IN2)->type.dimen;                                                                     \
+    numRows1 = ((psImage* )IN1)->numRows;                                                                     \
+    numCols1 = ((psImage* )IN1)->numCols;                                                                     \
+    \
+    if(dim2 == PS_DIMEN_VECTOR) { /* Regular vectors */                                                      \
+        if(n2!=numRows1) {                                                                                   \
+            psError(__func__, ": Inconsistent element count: %d vs %d", n2, numRows1);                       \
+            return OUT;                                                                                      \
+        }                                                                                                    \
+        \
+        i2 = ((psVector* )IN2)->data.TYPE;                                                                    \
+        for(j = 0; j < numRows1; j++, i1++) {                                                                \
+            o  = ((psImage* )OUT)->data.TYPE[j];                                                              \
+            i1 = ((psImage* )IN1)->data.TYPE[j];                                                              \
+            for(i = 0; i < numCols1; i++, o++, i1++) {                                                       \
+                *o = OP;                                                                                     \
+            }                                                                                                \
+        }                                                                                                    \
+    } else {  /* Transposed vectors */                                                                       \
+        if(n2!=numCols1) {                                                                                   \
+            psError(__func__, ": Inconsistent element count: %d vs %d", n2, numCols1);                       \
+            return OUT;                                                                                      \
+        }                                                                                                    \
+        \
+        for(j = 0; j < numRows1; j++) {                                                                      \
+            o  = ((psImage* )OUT)->data.TYPE[j];                                                              \
+            i1 = ((psVector* )IN2)->data.TYPE;                                                                \
+            i2 = ((psImage* )IN1)->data.TYPE[j];                                                              \
+            for(i = 0; i < numCols1; i++, o++, i2++, i1++) {                                                 \
+                *o = OP;                                                                                     \
+            }                                                                                                \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+#define IMAGE_IMAGE(OUT,IN1,OP,IN2,TYPE)                                                                     \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int numRows1 = 0;                                                                                        \
+    int numCols1 = 0;                                                                                        \
+    int numRows2 = 0;                                                                                        \
+    int numCols2 = 0;                                                                                        \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    ps##TYPE *i2 = NULL;                                                                                     \
+    numRows1 = ((psImage* )IN1)->numRows;                                                                     \
+    numCols1 = ((psImage* )IN1)->numCols;                                                                     \
+    numRows2 = ((psImage* )IN2)->numRows;                                                                     \
+    numCols2 = ((psImage* )IN2)->numCols;                                                                     \
+    if(numRows1!=numRows2 || numCols1!=numCols2) {                                                           \
+        psError(__func__, ": Inconsistent element count: numRows: %d vs %d numCols: %d vs %d", numRows1,     \
+                numRows2, numCols1, numCols2);                                                               \
+        return OUT;                                                                                          \
+    }                                                                                                        \
+    for(j = 0; j < numRows1; j++) {                                                                          \
+        o  = ((psImage* )OUT)->data.TYPE[j];                                                                  \
+        i1 = ((psImage* )IN1)->data.TYPE[j];                                                                  \
+        i2 = ((psImage* )IN2)->data.TYPE[j];                                                                  \
+        for(i = 0; i < numCols1; i++, o++, i1++, i2++) {                                                     \
+            *o = OP;                                                                                         \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+// Preprocessor macro function to create arithmetic function based on input type
+#define BINARY_TYPE(DIM1,DIM2,OUT,IN1,OP,IN2)                                                                \
+switch (IN1->type) {                                                                                         \
+case PS_TYPE_S32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_F32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,F32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_F64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,F64);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_C32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,C32);                                                                       \
+    break;                                                                                                   \
+default:                                                                                                     \
+case PS_TYPE_S8:                                                                                             \
+case PS_TYPE_U8:                                                                                             \
+case PS_TYPE_S16:                                                                                            \
+case PS_TYPE_U16:                                                                                            \
+case PS_TYPE_U32:                                                                                            \
+case PS_TYPE_S64:                                                                                            \
+case PS_TYPE_U64:                                                                                            \
+case PS_TYPE_C64:                                                                                            \
+    psError(__func__, ": Invalid PS_TYPE: %d", IN1->type);                                                   \
+}
+
+// Preprocessor macro function to create arithmetic function operation name
+#define BINARY_OP(DIM1,DIM2,OUT,IN1,OP,IN2)                                                                  \
+if(!strncmp(OP, "+", 1)) {                                                                                   \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 + *i2,IN2);                                                            \
+} else if(!strncmp(OP, "-", 1)) {                                                                            \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 - *i2,IN2);                                                            \
+} else if(!strncmp(OP, "*", 1)) {                                                                            \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 * *i2,IN2);                                                            \
+} else if(!strncmp(OP, "/", 1)) {                                                                            \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,psNanDiv(*i1,*i2),IN2);                                                    \
+} else if(!strncmp(OP, "^", 1)) {                                                                            \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN1->type)) {                                                                \
+        BINARY_TYPE(DIM1,DIM2,OUT,IN1,cpow(*i1,*i2),IN2);                                                    \
+    } else {                                                                                                 \
+        BINARY_TYPE(DIM1,DIM2,OUT,IN1,pow(*i1,*i2),IN2);                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "min", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN1->type)) {                                                                \
+        psError(__func__, ": Minimum operation not supported for complex numbers");                          \
+    } else {                                                                                                 \
+        BINARY_TYPE(DIM1,DIM2,OUT,IN1,fmin(*i1,*i2),IN2);                                                    \
+    }                                                                                                        \
+} else if(!strncmp(OP, "max", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN1->type)) {                                                                \
+        psError(__func__, ": Maximum operation not supported for complex numbers");                          \
+    } else {                                                                                                 \
+        BINARY_TYPE(DIM1,DIM2,OUT,IN1,fmax(*i1,*i2),IN2);                                                    \
+    }                                                                                                        \
+} else {                                                                                                     \
+    psError(__func__, ": Invalid operation: %s", OP);                                                        \
+}
+
+void *psBinaryOp(void *out, void *in1, char *op, void *in2)
+{
+    psDimen dim1 = 0;
+    psDimen dim2 = 0;
+    psDimen dimOut = 0;
+    psElemType elType1 = 0;
+    psElemType elType2 = 0;
+    psElemType elTypeOut = 0;
+    psType* psType1 = NULL;
+    psType* psType2 = NULL;
+    psType* psTypeOut = NULL;
+
+    psTypeOut = (psType* ) out;
+    if (psTypeOut == NULL) {
+        psError(__func__, ": Line %d - Null out argument", __LINE__);
+        return out;
+    }
+
+    psType1 = (psType* ) in1;
+    if (psType1 == NULL) {
+        psError(__func__, ": Line %d - Null in1 argument", __LINE__);
+        return out;
+    }
+
+    psType2 = (psType* ) in2;
+    if (psType2 == NULL) {
+        psError(__func__, ": Line %d - Null in2 argument", __LINE__);
+        return out;
+    }
+
+    if (op == NULL) {
+        psError(__func__, ": Line %d - Null op argument", __LINE__);
+        return out;
+    }
+
+    dim1 = psType1->dimen;
+    dim2 = psType2->dimen;
+    dimOut = psTypeOut->dimen;
+    elType1 = psType1->type;
+    elType2 = psType2->type;
+    elTypeOut = psTypeOut->type;
+
+    if (elType1 != elType2 && elType1 != elTypeOut) {
+        psError(__func__, ": Line %d - Element types for arguments inconsistent: (%d, %d, %d)", __LINE__,
+                elType1, elType2, elTypeOut);
+        return out;
+    }
+
+    if (dim1 == PS_DIMEN_OTHER || dim2 == PS_DIMEN_OTHER || dimOut == PS_DIMEN_OTHER) {
+        psError(__func__, ": Line %d - PS_DIMEN_OTHER not allowed for arguments: (%d, %d, %d)", __LINE__,
+                dim1, dim2, dimOut);
+        return out;
+    }
+
+    if (dim1 == PS_DIMEN_VECTOR) {
+        if (((psVector* ) in1)->n == 0) {
+            psError(__func__, ": Line %d - Vector contains zero elements");
+        }
+    } else if (dim1 == PS_DIMEN_IMAGE) {
+        if (((psImage* ) in1)->numCols == 0 || ((psImage* ) in1)->numRows == 0) {
+            psError(__func__, ": Line %d - Image contains zero length row or cols");
+        }
+    }
+
+    if (dim2 == PS_DIMEN_VECTOR) {
+        if (((psVector* ) in2)->n == 0) {
+            psError(__func__, ": Line %d - Vector contains zero elements");
+        }
+    } else if (dim2 == PS_DIMEN_IMAGE) {
+        if (((psImage* ) in2)->numCols == 0 || ((psImage* ) in2)->numRows == 0) {
+            psError(__func__, ": Line %d - Image contains zero length row or cols");
+        }
+    }
+
+    if (dim1 == PS_DIMEN_SCALAR) {
+        if (dim2 == PS_DIMEN_SCALAR) {
+            BINARY_OP(SCALAR, SCALAR, out, psType1, op, psType2);       // scalar op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            BINARY_OP(SCALAR, VECTOR, out, psType1, op, psType2);       // scalar op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            BINARY_OP(SCALAR, IMAGE, out, psType1, op, psType2);        // scalar op image
+        } else {
+            psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
+        }
+    } else if (dim1 == PS_DIMEN_VECTOR || dim1 == PS_DIMEN_TRANSV) {
+        if (dim2 == PS_DIMEN_SCALAR) {
+            BINARY_OP(VECTOR, SCALAR, out, psType1, op, psType2);       // vector op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            BINARY_OP(VECTOR, VECTOR, out, psType1, op, psType2);       // vector op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            BINARY_OP(VECTOR, IMAGE, out, psType1, op, psType2);        // vector op image
+        } else {
+            psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
+        }
+    } else if (dim1 == PS_DIMEN_IMAGE) {
+        if (dim2 == PS_DIMEN_SCALAR) {
+            BINARY_OP(IMAGE, SCALAR, out, psType1, op, psType2);        // image op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            BINARY_OP(IMAGE, VECTOR, out, psType1, op, psType2);        // image op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            BINARY_OP(IMAGE, IMAGE, out, psType1, op, psType2); // image op image
+        } else {
+            psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
+        }
+    } else {
+        psError(__func__, ": Line %d - Invalid dimensionality for in1 arg: %d", __LINE__, dim1);
+    }
+
+    return out;
+}
+
+// Unary SCALAR operations
+#define SCALAR(OUT,IN,OP,TYPE)                                                                               \
+{                                                                                                            \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    o  = &((psScalar* )OUT)->data.TYPE;                                                                       \
+    i1 = &((psScalar* )IN)->data.TYPE;                                                                        \
+    *o = OP;                                                                                                 \
+}
+
+// Unary IMAGE operations
+#define VECTOR(OUT,IN,OP,TYPE)                                                                               \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int nIn = 0;                                                                                             \
+    int nOut = 0;                                                                                            \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    nIn = ((psVector* )IN)->n;                                                                                \
+    nOut = ((psVector* )OUT)->n;                                                                              \
+    if(nIn != nOut) {                                                                                        \
+        psError(__func__, ": Inconsistent element count: %d vs %d", nIn, nOut);                              \
+        return OUT;                                                                                          \
+    }                                                                                                        \
+    o  = ((psVector* )OUT)->data.TYPE;                                                                        \
+    i1 = ((psVector* )IN)->data.TYPE;                                                                         \
+    for(i = 0; i < nIn; i++, o++, i1++) {                                                                    \
+        *o = OP;                                                                                             \
+    }                                                                                                        \
+}
+
+// Unary IMAGE operations
+#define IMAGE(OUT,IN,OP,TYPE)                                                                                \
+{                                                                                                            \
+    int i = 0;                                                                                               \
+    int j = 0;                                                                                               \
+    int numRowsIn = 0;                                                                                       \
+    int numColsIn = 0;                                                                                       \
+    int numRowsOut = 0;                                                                                      \
+    int numColsOut = 0;                                                                                      \
+    ps##TYPE *o = NULL;                                                                                      \
+    ps##TYPE *i1 = NULL;                                                                                     \
+    numRowsIn = ((psImage* )IN)->numRows;                                                                     \
+    numColsIn = ((psImage* )IN)->numCols;                                                                     \
+    numRowsOut = ((psImage* )OUT)->numRows;                                                                   \
+    numColsOut = ((psImage* )OUT)->numCols;                                                                   \
+    if(numRowsIn!=numRowsOut || numColsIn!=numColsOut) {                                                     \
+        psError(__func__, ": Inconsistent element count: numRows: %d vs %d numCols: %d vs %d", numRowsIn,    \
+                numRowsOut, numColsIn, numColsOut);                                                          \
+        return OUT;                                                                                          \
+    }                                                                                                        \
+    for(j = 0; j < numRowsIn; j++) {                                                                         \
+        o  = ((psImage* )OUT)->data.TYPE[j];                                                                  \
+        i1 = ((psImage* )IN)->data.TYPE[j];                                                                   \
+        for(i = 0; i < numColsIn; i++, o++, i1++) {                                                          \
+            *o = OP;                                                                                         \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+// Preprocessor macro function to create arithmetic function based on input type
+#define UNARY_TYPE(DIM,OUT,IN,OP)                                                                            \
+switch (IN->type) {                                                                                          \
+case PS_TYPE_S32:                                                                                            \
+    DIM(OUT,IN,OP,S32);                                                                                      \
+    break;                                                                                                   \
+case PS_TYPE_F32:                                                                                            \
+    DIM(OUT,IN,OP,F32);                                                                                      \
+    break;                                                                                                   \
+case PS_TYPE_F64:                                                                                            \
+    DIM(OUT,IN,OP,F64);                                                                                      \
+    break;                                                                                                   \
+case PS_TYPE_C32:                                                                                            \
+    DIM(OUT,IN,OP,C32);                                                                                      \
+    break;                                                                                                   \
+default:                                                                                                     \
+case PS_TYPE_S8:                                                                                             \
+case PS_TYPE_U8:                                                                                             \
+case PS_TYPE_S16:                                                                                            \
+case PS_TYPE_U16:                                                                                            \
+case PS_TYPE_U32:                                                                                            \
+case PS_TYPE_S64:                                                                                            \
+case PS_TYPE_U64:                                                                                            \
+case PS_TYPE_C64:                                                                                            \
+    psError(__func__, ": Invalid PS_TYPE: %d", IN->type);                                                    \
+}
+
+// Preprocessor macro function to create arithmetic function operation name. Functions below that add
+// FLT_EPSILON are done so to align results with a 64 bit computing architecture
+#define UNARY_OP(DIM,OUT,IN,OP)                                                                              \
+if(!strncmp(OP, "abs", 3)) {                                                                                 \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cabs(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,fabs(*i1));                                                                    \
+    }                                                                                                        \
+} else if(!strncmp(OP, "exp", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cexp(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,exp(*i1));                                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "ln", 2)) {                                                                           \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,clog(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,log(*i1));                                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "ten", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cpow(10.0,*i1));                                                               \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,pow(10.0,*i1));                                                                \
+    }                                                                                                        \
+} else if(!strncmp(OP, "log", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,clog(*i1)/log(10.0));                                                          \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,log10(*i1));                                                                   \
+    }                                                                                                        \
+} else if(!strncmp(OP, "sin", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,csin(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,sin(*i1));                                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "dsin", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,csin(*i1*D2R));                                                                \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,sin(*i1*D2R));                                                                 \
+    }                                                                                                        \
+} else if(!strncmp(OP, "cos", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,ccos(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cos(*i1));                                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "dcos", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,ccos(*i1*D2R));                                                                \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cos(*i1*D2R));                                                                 \
+    }                                                                                                        \
+} else if(!strncmp(OP, "tan", 3)) {                                                                          \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,ctan(*i1));                                                                    \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,tan(*i1));                                                                     \
+    }                                                                                                        \
+} else if(!strncmp(OP, "dtan", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,ctan(*i1*D2R));                                                                \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,tan(*i1*D2R));                                                                 \
+    }                                                                                                        \
+} else if(!strncmp(OP, "asin", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,casin(*i1));                                                                   \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,asin(*i1));                                                                    \
+    }                                                                                                        \
+} else if(!strncmp(OP, "dasin", 5)) {                                                                        \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,R2D*casin(*i1));                                                               \
+    } else if(PS_IS_PSELEMTYPE_INT(IN->type)) {                                                              \
+        UNARY_TYPE(DIM,OUT,IN,(R2D*asin(*i1)));                                                              \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,(R2D*asin(*i1)));                                                              \
+    }                                                                                                        \
+} else if(!strncmp(OP, "acos", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,cacos(*i1));                                                                   \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,acos(*i1));                                                                    \
+    }                                                                                                        \
+} else if(!strncmp(OP, "dacos", 5)) {                                                                        \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,R2D*cacos(*i1));                                                               \
+    } else if(PS_IS_PSELEMTYPE_INT(IN->type)) {                                                              \
+        UNARY_TYPE(DIM,OUT,IN,(R2D*acos(*i1)));                                                              \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,R2D*acos(*i1));                                                                \
+    }                                                                                                        \
+} else if(!strncmp(OP, "atan", 4)) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,catan(*i1));                                                                   \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,atan(*i1));                                                                    \
+    }                                                                                                        \
+} else if(!strncmp(OP, "datan", 5)) {                                                                        \
+    if(PS_IS_PSELEMTYPE_COMPLEX(IN->type)) {                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,R2D*catan(*i1));                                                               \
+    } else {                                                                                                 \
+        UNARY_TYPE(DIM,OUT,IN,R2D*atan(*i1));                                                                \
+    }                                                                                                        \
+} else {                                                                                                     \
+    psError(__func__, ": Invalid operation: %s", OP);                                                        \
+}
+
+void *psUnaryOp(void *out, void *in, char *op)
+{
+    psDimen dimIn = 0;
+    psDimen dimOut = 0;
+    psElemType elTypeIn = 0;
+    psElemType elTypeOut = 0;
+    psType* psTypeIn = NULL;
+    psType* psTypeOut = NULL;
+
+    psTypeOut = (psType* ) out;
+    if (psTypeOut == NULL) {
+        psError(__func__, ": Line %d - Null out argument", __LINE__);
+        return out;
+    }
+
+    psTypeIn = (psType* ) in;
+    if (psTypeIn == NULL) {
+        psError(__func__, ": Line %d - Null in argument", __LINE__);
+        return out;
+    }
+
+    if (op == NULL) {
+        psError(__func__, ": Line %d - Null op argument", __LINE__);
+        return out;
+    }
+
+    dimIn = psTypeIn->dimen;
+    dimOut = psTypeOut->dimen;
+    elTypeIn = psTypeIn->type;
+    elTypeOut = psTypeOut->type;
+
+    if (elTypeIn != elTypeOut) {
+        psError(__func__, ": Line %d - Element types for arguments inconsistent: (%d, %d)", __LINE__,
+                elTypeIn, elTypeOut);
+        return out;
+    }
+
+    if (dimIn != dimOut) {
+        psError(__func__, ": Line %d - Dimensionality for arguments inconsistent: (%d, %d)", __LINE__,
+                dimIn, dimOut);
+        return out;
+    }
+
+    if (dimIn == PS_DIMEN_OTHER || dimOut == PS_DIMEN_OTHER) {
+        psError(__func__, ": Line %d - PS_DIMEN_OTHER not allowed for arguments: (%d, %d)", __LINE__,
+                dimIn, dimOut);
+        return out;
+    }
+
+    if (dimIn == PS_DIMEN_VECTOR) {
+        if (((psVector* ) in)->n == 0) {
+            psError(__func__, ": Line %d - Vector contains zero elements");
+        }
+    } else if (dimIn == PS_DIMEN_IMAGE) {
+        if (((psImage* ) in)->numCols == 0 || ((psImage* ) in)->numRows == 0) {
+            psError(__func__, ": Line %d - Image contains zero length row or cols");
+        }
+    }
+
+    if (dimOut == PS_DIMEN_VECTOR) {
+        if (((psVector* ) out)->n == 0) {
+            psError(__func__, ": Line %d - Vector contains zero elements");
+        }
+    } else if (dimOut == PS_DIMEN_IMAGE) {
+        if (((psImage* ) out)->numCols == 0 || ((psImage* ) out)->numRows == 0) {
+            psError(__func__, ": Line %d - Image contains zero length row or cols");
+        }
+    }
+
+    if (dimIn == PS_DIMEN_SCALAR) {
+        UNARY_OP(SCALAR, out, psTypeIn, op);    // scalar
+    } else if (dimIn == PS_DIMEN_VECTOR || dimIn == PS_DIMEN_TRANSV) {
+        UNARY_OP(VECTOR, out, psTypeIn, op);    // vector
+    } else if (dimIn == PS_DIMEN_IMAGE) {
+        UNARY_OP(IMAGE, out, psTypeIn, op);     // image
+    } else {
+        psError(__func__, ": Line %d - Invalid dimensionality for in arg: %d", __LINE__, dimIn);
+    }
+
+    return out;
+}
Index: /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMatrixVectorArithmetic.h	(revision 1553)
@@ -0,0 +1,88 @@
+
+/** @file  psMatrixVectorArithmetic.h
+ *
+ *  @brief Provides unary and binary functions for simple matrix and vector element operations. Functions
+ *  include:
+ *
+ *      Addition (+)
+ *      Subtraction (-)
+ *      Multiplication (*)
+ *      Division (/)
+ *      Power (^)
+ *      Minimum (min)
+ *      Maximum (max)
+ *      Absolute value (abs)
+ *      Exponent (exp)
+ *      Natural Log (ln)
+ *      Power of 10 (ten)
+ *      Log (log)
+ *      Sine (sin or dsin)
+ *      Cosine (cos or dcos)
+ *      Tangent (tan or dtan)
+ *      Arcsine (asin or dasin)
+ *      Arccosine (acos or dacos)
+ *      Arctan (atan or datan)
+ *
+ *  Currently only vector-vector and image-image binary operations are supported.
+ *
+ *  @ingroup MatrixVectorArithmetic
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 02:37:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSMATRIX_VECTOR_ARITHMETIC_H
+#define PSMATRIX_VECTOR_ARITHMETIC_H
+
+/// @addtogroup MatrixVectorArithmetic
+/// @{
+
+/** Perform simple binary arithmetic with images or vectors
+ *
+ *  Performs addition, subtraction, multiplication, division, power, minumum, and maximum arithmetic
+ *  operations with images and vectors. Uses the form:
+ *
+ *      out = in1 op in2,
+ *
+ *      Where op is: "+", "-", "*", "/", "^", "min", or "max"
+ *
+ *  This function only supports vector-vector or image-image opertions.
+ *
+ *  @return  psType* : Pointer to either psImage or psVector.
+ */
+psType* psBinaryOp(
+    void *out,                         ///< Output type, either psImage or psVector.
+    void *in1,                         ///< First input, either psImage or psVector.
+    char *op,                          ///< Operator.
+    void *in2                          ///< Second input, either psImage or psVector.
+);
+
+/** Perform simple unary arithmetic with images or vectors
+ *
+ *  Performs absolute value, exponent, natural log, power of 10, log, sine, cosine, tangent, arcsine,
+ *  arccosine, or arctan. operations with images and vectors. Uses the form:
+ *
+ *     out = op(in),
+ *
+ *     Where op is: "abs", "exp", "ln", "ten", "log", "sin", "cos", "tan" "asin", "acos", "atan", "dsin",
+ *                  "dcos", dtan", "dasin", "dacos", or "datan".
+ *
+ *  Trigometric Operations with "d" prefix use units of degrees. Those without are in radians.
+ *
+ *  This function only supports vector-vector or image-image opertions.
+ *
+ *  @return  psType* : Pointer to either psImage or psVector.
+ */
+psType* psUnaryOp(
+    void *out,                         ///< Output type, either psImage or psVector.
+    void *in,                          ///< Input, either psImage or psVector.
+    char *op                           ///< Operator.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psMinimize.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMinimize.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMinimize.c	(revision 1553)
@@ -0,0 +1,940 @@
+
+/** @file  psMinimize.c
+ *  \brief basic minimization functions
+ *  @ingroup Math
+ *
+ *  This file will contain functions to minimize an arbitrary function at
+ *  a data point, fit an arbitrary function to a set of data points, and
+ *  fit a 1-D polynomial to a set of data points.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 03:17:03 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************/
+
+/* INCLUDE FILES                                                             */
+
+/*****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include <gsl/gsl_multifit_nlin.h>
+#include <gsl/gsl_multimin.h>
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include "psMatrix.h"
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+#define MAX_LMM_ITERATIONS 100
+#define MAX_MINIMIZE_ITERATIONS 100
+
+/** Preprocessor macro to generate error on a NULL 1DPolynomial */
+#define PS_CHECK_NULL_1DPOLY(NAME)                                                          \
+if (NAME == NULL || NAME->coeff == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error on a NULL vector */
+#define PS_CHECK_NULL_VECTOR(NAME)                                                          \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_EMPTY_VECTOR(NAME)                                                          \
+if (NAME->n < 1) {                                                                                  \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME);                             \
+}
+
+/** Preprocessor macro to generate error on differing size vectors */
+#define PS_CHECK_VECTOR_SIZE_EQUAL(VEC1, VEC2)                                                          \
+if (VEC1->n != VEC2->n) {               \
+    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
+}
+
+/** Preprocessor macro to generate error on a NULL image */
+#define PS_CHECK_NULL_IMAGE(NAME)                                                           \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error for zero length rows or columns */
+#define PS_CHECK_EMPTY_IMAGE(NAME)                                                           \
+if (NAME->numCols < 1 || NAME->numRows < 1) {                                                       \
+    psError(__func__,"Invalid operation: %s has zero rows or columns (%dx%d).", #NAME,              \
+            NAME->numCols, NAME->numRows);                                                          \
+}
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+typedef struct
+{
+    size_t n;                   // Number of data points points in domain.
+    int paramCount;             // Number of non-masked parameters.
+    psVector* restrict initialGuess;
+    const psImage* restrict domain;
+    const psVector* restrict data;
+    const psVector* restrict errors;
+    const psVector* restrict paramMask;
+    psMinimizeFunction evalModel;
+    psMinimizeFunctionDeriv d_evalModel;
+}
+psMinChi2Data;
+
+typedef struct
+{
+    int paramCount;             // Number of non-masked parameters.
+    psVector* restrict initialGuess;
+    const psVector* restrict coord;
+    const psVector* restrict paramMask;
+    psMinimizeFunction evalModel;
+    psMinimizeFunctionDeriv d_evalModel;
+}
+psMinimizeData;
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+/******************************************************************************
+p_psMinFunc(*params, *funcData): We use the GSL procedure
+gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
+by the user.  That GSL procedure requires the function to be minimized to be
+in a different format than the psLib format.  The purpose of this procedure
+is to serve as a GSL-format wrapper for the user-supplied procedure which is
+to be minimized.
+ 
+    params: The parameters of the function to be minimized.  These will be
+ varied by GSL in order to minimize the function.
+ 
+    funcData: a private psLib struct which contains the data point to be
+ minimized, the function and derivative function pointers, an initial
+ guess at the parameters, an option parameter mask, etc.
+ *****************************************************************************/
+double p_psMinFunc(const gsl_vector * params, void *funcData)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psVector* restrict coord = ((psMinimizeData* ) funcData)->coord;
+    const psVector* restrict mask = ((psMinimizeData* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinimizeData* ) funcData)->initialGuess;
+    psMinimizeFunction evalModel = ((psMinimizeData* ) funcData)->evalModel;
+    psVector* inputParameterList = NULL;
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Call the user-supplied function.
+    tmpf = evalModel(inputParameterList, coord);
+
+    // Free allocated memory and return the value of the function.
+    psFree(inputParameterList);
+    return (tmpf);
+}
+
+/******************************************************************************
+p_psMinFuncDeriv(*params, *funcData):  a GSL-like wrapper for the
+user-supplied procedure which calculates the derviative of the function to be
+minimized.
+ 
+    params: The parameters of the function to be minimized.  These will be
+ varied by GSL in order to minimize the function.
+ 
+    funcData: a private psLib struct which contains the data point to be
+ minimized, the function and derivative function pointers, an initial
+ guess at the parameters, an option parameter mask, etc.
+ 
+    df: we calculate the derivative of the function w.r.t. to each parameter
+ in "params" and return those derivatives in this psVector.
+ *****************************************************************************/
+void p_psMinFuncDeriv(const gsl_vector * params, void *funcData, gsl_vector * df)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psVector* restrict coord = ((psMinimizeData* ) funcData)->coord;
+    const psVector* restrict mask = ((psMinimizeData* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinimizeData* ) funcData)->initialGuess;
+    psMinimizeFunctionDeriv d_evalModel = ((psMinimizeData* ) funcData)->d_evalModel;
+    psVector* inputParameterList = NULL;
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the derivative w.r.t. each parameter.
+    // NOTE: we can probably remove the calls for masked parameters.
+    for (i = 0; i < initialGuess->n; i++) {
+        tmpf = d_evalModel(inputParameterList, coord, i);
+        gsl_vector_set(df, i, tmpf);
+    }
+
+    // Free allocated memory.
+    psFree(inputParameterList);
+}
+
+/******************************************************************************
+    Compute both p_psMinFunc and p_psMinFuncDeriv together.
+ *****************************************************************************/
+void p_psMinFuncFuncDeriv(const gsl_vector * params, void *funcData, double *f, gsl_vector * df)
+{
+    *f = p_psMinFunc(params, funcData);
+    p_psMinFuncDeriv(params, funcData, df);
+}
+
+// The first argument to evalModel() and d_evalModel() specifies the data
+// point.  It must have the same size as the second dimension of *domain.
+// The second argument must have the same size as *initialGuess and
+// *paramMask.
+
+/******************************************************************************
+p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL procedure
+gsl_multifit_fdfsolver_iterate() to fit an arbitrary function, supplied by
+the user, to a set of data points.  That GSL procedure requires the function
+to be fit to be in a different format than the psLib format.  The purpose of
+this procedure is to serve as a GSL-format wrapper for the user-supplied
+procedure which is to be fit to the data.
+ 
+    params: These are the parameters which are to be varied by GSL in order
+  to minimize chi2 over the data set.
+ 
+    funcData: this data structure contains the input values over which the
+  function will be evaluated, the expected value of the function at
+  those points, the amount of error tolerable at those points, a mask
+  vector which specifies which parameters to the function are to be
+  constant, and an initial guess at the parameters.
+ 
+    outData: The function is evaluated at each point, then subtract the
+  expected value and divide by the error.
+ *****************************************************************************/
+int p_psMinChi2Func(const gsl_vector * params, void *funcData, gsl_vector * outData)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psImage* restrict domain = ((psMinChi2Data* ) funcData)->domain;
+    const psVector* restrict data = ((psMinChi2Data* ) funcData)->data;
+    const psVector* restrict errors = ((psMinChi2Data* ) funcData)->errors;
+    const psVector* restrict mask = ((psMinChi2Data* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinChi2Data* ) funcData)->initialGuess;
+    psMinimizeFunction evalModel = ((psMinChi2Data* ) funcData)->evalModel;
+    psVector* inputParameterList = NULL;
+    psVector* tmpVecPtr = NULL;
+
+    tmpVecPtr = psVectorAlloc(domain->numCols, PS_TYPE_F32);
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the function at each data point.
+    for (i = 0; i < domain->numRows; i++) {
+        for (j = 0; j < domain->numCols; j++) {
+            tmpVecPtr->data.F32[j] = domain->data.F32[i][j];
+        }
+        tmpf = evalModel(tmpVecPtr, inputParameterList);
+
+        gsl_vector_set(outData, i, (tmpf - data->data.F32[i]) / errors->data.F32[i]);
+    }
+
+    // Free allocated memory.
+    psFree(inputParameterList);
+    psFree(tmpVecPtr);
+
+    return GSL_SUCCESS;
+}
+
+/******************************************************************************
+p_psMinChi2FuncDeriv(*x, *funcData, *outdata): a GSL-like wrapper for the
+user-supplied procedure which calculates the derviative of the function to be
+minimized.
+    params: These are the parameters which are to be varied by GSL in order
+  to minimize chi2 over the data set.
+ 
+    funcData: this data structure contains the input values over which the
+  function will be evaluated, the expected value of the function at
+  those points, the amount of error tolerable at those points, a mask
+  vector which specifies which parameters to the function are to be
+  constant, and an initial guess at the parameters.
+ 
+    J: The derivative is evaluated at each point and w.r.t. each parameter
+ and returned in this data structure.
+ *****************************************************************************/
+int p_psMinChi2FuncDeriv(const gsl_vector * params, void *funcData, gsl_matrix * J)
+{
+    const psImage* restrict domain = ((psMinChi2Data* ) funcData)->domain;
+    const psVector* restrict errors = ((psMinChi2Data* ) funcData)->errors;
+    const psVector* restrict mask = ((psMinChi2Data* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinChi2Data* ) funcData)->initialGuess;
+    psVector* inputParameterList = NULL;
+    psVector* tmpVecPtr = NULL;
+    psMinimizeFunctionDeriv d_evalModel = ((psMinChi2Data* ) funcData)->d_evalModel;
+
+    size_t i;
+    int j;
+    float tmpf;
+
+    tmpVecPtr = psVectorAlloc(domain->numCols, PS_TYPE_F32);
+
+    // The GSL routines will call this functions with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the derivtaive at each data point, and w.r.t. each parameter.
+    for (i = 0; i < domain->numRows; i++) {
+        for (j = 0; j < tmpVecPtr->n; j++) {
+            tmpVecPtr->data.F32[j] = domain->data.F32[i][j];
+        }
+
+        for (j = 0; j < inputParameterList->n; j++) {
+            tmpf = d_evalModel(tmpVecPtr, inputParameterList, j);
+            gsl_matrix_set(J, i, j, (tmpf / errors->data.F32[i]));
+        }
+    }
+
+    psFree(inputParameterList);
+    psFree(tmpVecPtr);
+    return GSL_SUCCESS;
+}
+
+int p_psMinChi2FuncFuncDeriv(const gsl_vector * params, void *funcData, gsl_vector * f, gsl_matrix * J)
+{
+    p_psMinChi2Func(params, funcData, f);
+    p_psMinChi2FuncDeriv(params, funcData, J);
+
+    return GSL_SUCCESS;
+}
+
+/******************************************************************************
+p_psBuildSums1D(x, polyOrder, sums): this routine calculates the powers of
+input parameter "x" between 0 and input parameter polyOrder.  The result is
+returned as a psVector sums.
+ *****************************************************************************/
+void p_psBuildSums1D(double x, int polyOrder, psVector* sums)
+{
+    int i = 0;
+    double xSum = 0.0;
+
+    xSum = 1.0;
+    for (i = 0; i <= polyOrder; i++) {
+        sums->data.F64[i] = xSum;
+        xSum *= x;
+    }
+}
+
+/******************************************************************************
+p_psBuildSums1D(x): this routine returns a psVector with "x" elements.  The
+values of the vector will be scaled uniformly between -1.0 and 1.0.
+ *****************************************************************************/
+psVector* psBuildImageScalingFactors(int x)
+{
+    int i = 0;                  // loop index variable.
+    psVector* imageScalingFactors = NULL;
+
+    imageScalingFactors = psVectorAlloc(x, PS_TYPE_F32);
+
+    for (i = 0; i < x; i++) {
+        imageScalingFactors->data.F32[i] = (((float)2 * i) / ((float)x)) - 1.0;
+    }
+
+    return (imageScalingFactors);
+}
+
+/******************************************************************************
+CURRENTLY NOT IN USE.
+ 
+p_psPolyOrderCheck(A, N, *indx, *B, polyOrder,*flag) This routine checks if
+all polyOrder-th terms in the polyOrder-th order sky background polynomial
+defined by the coefficients in the array B[] are consistent with zero.  If
+true, then *flag is set to 1.  Otherwise, *flag is set to 0.  The matrix
+inversion code in the middle of this procedure draws from Numerical Recipes
+in C page 48.
+Input:
+    A       This is the LUD decomposition of the original matrix A.
+    N       The size of the matrix (plus 1, actually, since offset 1).
+    indx    misc Numerical Recipes data structure.
+    B       The coefficients of the sky polynomial.
+    polyOrder The degree of the sky polynomial.
+Output:
+    *flag   Set this to 1 if we must recalculate the coefficients.
+ *****************************************************************************/
+void p_psPolyOrderCheck(float **A, int N, int *indx, float *B, int polyOrder, int *flag)
+{
+    float **y = NULL;           // This 2-D matrix will hold A^-1
+    float *col = NULL;          // misc NumerRecipes data structure
+    float *error = NULL;        // will hold the sqrt() of the
+
+    // diagonal of y[][].
+    int i = 0;                  // loop-index variable
+    int j = 0;                  // loop-index variable
+    int numPolyTerms = 0;       // The number of terms in the
+
+    // polynomial.
+    int lastTerm = 0;           // The index location of the first
+
+    // n-th order term in array B[].
+    int firstTerm = 0;          // Index location of last such term.
+
+    // Allocate the necessary data structures for this procedure...
+    error = (float *)psAlloc((N + 1) * sizeof(float));
+    col = (float *)psAlloc((N + 1) * sizeof(float));
+    y = (float **)psAlloc((N + 1) * sizeof(float *));
+    for (i = 1; i <= N; i++) {
+        y[i] = (float *)psAlloc((N + 1) * sizeof(float));
+    }
+
+    // Invert the matrix A and put the result in y[][].  This code is taken
+    // from Numerical Recipes in C page 48.
+    for (j = 1; j <= N; j++) {
+        for (i = 1; i <= N; i++) {
+            col[i] = 0.0;
+        }
+        col[j] = 1.0;
+        // NOTE: substitue the LUD rotine
+        // lubksb(A, N, indx, col);
+        for (i = 1; i <= N; i++) {
+            y[i][j] = col[i];
+        }
+    }
+
+    // Determine where the first n-th order (in this comment, n equals
+    // polyOrder) polynomial term is stored in the matrix B[], and also were
+    // the last n-order term is stored.  Then we loop over all the n-order
+    // terms and check if they are consistent with zero.
+
+    numPolyTerms = (((polyOrder + 1) * (polyOrder + 2)) / 2);
+    lastTerm = numPolyTerms + 1;
+    firstTerm = lastTerm - polyOrder;
+    *flag = 1;
+    for (i = firstTerm; i <= lastTerm; i++) {
+        #ifdef DARWIN
+        error[i] = (float)sqrt(y[i][i]);
+        #else
+
+        error[i] = sqrtf(y[i][i]);
+        #endif
+
+        if (!((B[i] <= (2.0f * error[i])) && ((-2.0f * error[i]) <= B[i]))) {
+            *flag = 0;
+        }
+    }
+
+    // Free all memory allocated in this routine.
+    psFree(error);
+    psFree(col);
+    for (j = 1; j <= N; j++) {
+        psFree(y[j]);
+    }
+    psFree(y);
+}
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+/******************************************************************************
+psMinimize(initialGuess, myFunction, myFunctionDeriv, coord, paramMask):
+ 
+This routine must minimize an arbitrary function; it determines the set of
+parameters of that function such that the ...
+ *****************************************************************************/
+psVector* psMinimize(psVector* restrict initialGuess,
+                     psMinimizeFunction myFunction,
+                     psMinimizeFunctionDeriv myFunctionDeriv,
+                     const psVector* restrict coord,
+                     const psVector* restrict paramMask)
+{
+    int status;
+    int i = 0;
+    int j = 0;
+    int iter = 0;
+    gsl_multimin_function_fdf f;
+    const gsl_multimin_fdfminimizer_type *T;
+    gsl_multimin_fdfminimizer *s;
+    psMinimizeData inputData;
+    gsl_vector *x;
+
+    PS_CHECK_NULL_VECTOR(initialGuess);
+    PS_CHECK_EMPTY_VECTOR(initialGuess);
+    PS_CHECK_NULL_VECTOR(coord);
+    PS_CHECK_EMPTY_VECTOR(coord);
+    if (paramMask != NULL) {
+        PS_CHECK_NULL_VECTOR(paramMask);
+        PS_CHECK_EMPTY_VECTOR(paramMask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(initialGuess, paramMask);
+    }
+
+    inputData.initialGuess = initialGuess;
+    inputData.coord = coord;
+    inputData.paramMask = paramMask;
+    inputData.evalModel = myFunction;
+    inputData.d_evalModel = myFunctionDeriv;
+    inputData.paramCount = 0;
+
+    // If the user supplied a parameter mask, then count the number of
+    // non-masked elements.  This will be used later in allocating a vector
+    // for the parameters.
+    if (paramMask != NULL) {
+        for (i = 0; i < paramMask->n; i++) {
+            if (paramMask->data.U8[i] != 0) {
+                inputData.paramCount++;
+            }
+        }
+    } else {
+        inputData.paramCount = initialGuess->n;
+    }
+
+    // The initial guess at the parameters for the function are written into
+    // the vector inputParameterList.  If the paramMask is not NULL, then
+    // masked parameters are masked out.
+    x = gsl_vector_alloc(inputData.paramCount);
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                gsl_vector_set(x, j++, initialGuess->data.F32[i]);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            gsl_vector_set(x, i, initialGuess->data.F32[i]);
+        }
+    }
+    f.f = &p_psMinFunc;
+    f.df = &p_psMinFuncDeriv;
+    f.fdf = &p_psMinFuncFuncDeriv;
+    f.n = inputData.paramCount;
+    f.params = &inputData;
+
+    T = gsl_multimin_fdfminimizer_conjugate_fr;
+    s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount);
+    gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4);
+    do {
+        iter++;
+        status = gsl_multimin_fdfminimizer_iterate(s);
+
+        if (status)
+            break;
+
+        status = gsl_multimin_test_gradient(s->gradient, 1e-3);
+
+        if (status == GSL_SUCCESS)
+            printf("Minimum found at:\n");
+
+    } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS);
+
+    // In the above steps we had removed the masked elements from the
+    // the solver.  This next code blocks puts those masked elements
+    // into the solution.
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                initialGuess->data.F32[i] = gsl_vector_get(s->x, j++);
+            } else {
+                initialGuess->data.F32[i] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            initialGuess->data.F32[i] = gsl_vector_get(s->x, i);
+        }
+    }
+    return (initialGuess);
+}
+
+/******************************************************************************
+    This routine must determine the parameters of an arbitrary function
+    such that they best fit the supplied data points.
+ *****************************************************************************/
+psVector* psMinimizeChi2(psMinimizeFunction evalModel,
+                         psMinimizeFunctionDeriv DevalModel,
+                         const psImage* restrict domain,
+                         const psVector* restrict data,
+                         const psVector* restrict errors,
+                         psVector* restrict initialGuess,
+                         const psVector* restrict paramMask,
+                         float *chiSq)
+{
+    int numData = domain->numRows;      // Number of data points
+    int status;                 // Return status for the GSL solver.
+    int i = 0;                  // Loop index variable.
+    int j = 0;                  // Loop index variable.
+    int iter = 0;               // Iteration counter.
+    gsl_multifit_function_fdf f;        // GSL structure that contains the
+
+    // functions/derivative to be solved.
+    double *xInit = NULL;       // The initial guess at the parameters
+
+    // with masked parameters removed.
+    const gsl_multifit_fdfsolver_type *T;
+
+    // This tells GSL to use the Levenberg-
+    // Marquardt algorithm for chi2
+    // minimization.
+    gsl_multifit_fdfsolver *s;  // GSL data structure.
+    psMinChi2Data inputData;
+    float chiSqOld = 0.0;
+
+    PS_CHECK_NULL_IMAGE(domain);
+    PS_CHECK_EMPTY_IMAGE(domain);
+    PS_CHECK_NULL_VECTOR(data);
+    PS_CHECK_EMPTY_VECTOR(data);
+    PS_CHECK_NULL_VECTOR(errors);
+    PS_CHECK_EMPTY_VECTOR(errors);
+    PS_CHECK_NULL_VECTOR(initialGuess);
+    PS_CHECK_EMPTY_VECTOR(initialGuess);
+    PS_CHECK_VECTOR_SIZE_EQUAL(data, errors);
+    if (domain->numRows != data->n) {
+        psAbort(__func__, "Number of data points and data values not equal.");
+    }
+    if (paramMask != NULL) {
+        PS_CHECK_NULL_VECTOR(paramMask);
+        PS_CHECK_EMPTY_VECTOR(paramMask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(initialGuess, paramMask);
+    }
+
+    inputData.n = numData;
+    inputData.paramCount = 0;
+    inputData.initialGuess = initialGuess;
+    inputData.domain = domain;
+    inputData.data = data;
+    inputData.errors = errors;
+    inputData.paramMask = paramMask;
+    inputData.evalModel = evalModel;
+    inputData.d_evalModel = DevalModel;
+
+    // If the user supplied a parameter mask, then count the number of
+    // non-masked elements.  This will be used later in allocating a vector
+    // for the parameters.
+    if (paramMask != NULL) {
+        for (i = 0; i < paramMask->n; i++) {
+            if (paramMask->data.U8[i] != 0) {
+                inputData.paramCount++;
+            }
+        }
+    } else {
+        inputData.paramCount = initialGuess->n;
+    }
+
+    // The initial guess at the parameters for the function are written into
+    // the vector inputParameterList.  If the paramMask is not NULL, then those
+    // parameters are masked out.
+    xInit = (double *)psAlloc(inputData.paramCount * sizeof(double));
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                xInit[j++] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            xInit[i] = initialGuess->data.F32[i];
+        }
+    }
+
+    const gsl_rng_type *type;
+    gsl_rng *r;
+
+    gsl_rng_env_setup();
+
+    type = gsl_rng_default;
+    r = gsl_rng_alloc(type);
+
+    // Initialize the main data structure used by the GSL solver.  This will
+    // contain pointers to the function to be minimized, it's derivative
+    // function, the number of data points, the number of free parameters,
+    // and the data structures those functions use.
+
+    f.f = &p_psMinChi2Func;
+    f.df = &p_psMinChi2FuncDeriv;
+    f.fdf = &p_psMinChi2FuncFuncDeriv;
+    f.n = numData;
+    f.p = inputData.paramCount;
+    f.params = &inputData;
+
+    gsl_vector_view x = gsl_vector_view_array(xInit, inputData.paramCount);
+
+    T = gsl_multifit_fdfsolver_lmsder;
+    s = gsl_multifit_fdfsolver_alloc(T, numData, inputData.paramCount);
+    gsl_multifit_fdfsolver_set(s, &f, &x.vector);
+    *chiSq = 0.0;
+    chiSqOld = 0.0;
+    do {
+        iter++;
+        for (i = 0; i < initialGuess->n; i++) {
+            printf("Iteration %d: parameter %d is %.3f\n", iter, i, gsl_vector_get(s->x, i));
+        }
+        // Perform an iteration of the GSL solver.
+        status = gsl_multifit_fdfsolver_iterate(s);
+        printf("gsl_multifit_fdfsolver_iterate() status is %s\n", gsl_strerror(status));
+        for (i = 0; i < initialGuess->n; i++) {
+            printf("Iteration %d: parameter %d is %.3f\n", iter, i, gsl_vector_get(s->x, i));
+        }
+
+        // If there was a problem, abort.
+        if (status) {
+            psAbort(__func__, "gsl_multifit_fdfsolver_iterate(%s)\n", gsl_strerror(status));
+        }
+        // Test if the parameters changed by a small enough amount.
+        // NOTE: This wasn't working right when the parameters fit exactly.
+        // Figure out why.
+        // status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
+
+        // We test for convergence if chiSquared changes by less than 1.0
+        // as specified in the ADD.
+        *chiSq = gsl_blas_dnrm2(s->f);
+        printf("psMinimize.c: chiSq is %.3f\n", *chiSq);
+        if (fabs(*chiSq - chiSqOld) < 1.0) {
+            status = GSL_SUCCESS;
+        } else {
+            status = GSL_CONTINUE;
+        }
+        chiSqOld = *chiSq;
+
+    } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS);
+
+    // In the above steps we had removed the masked elements from the
+    // the solver.  This next code blocks puts those masked elements
+    // into the solution.
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                initialGuess->data.F32[i] = gsl_vector_get(s->x, j++);
+            } else {
+                initialGuess->data.F32[i] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            initialGuess->data.F32[i] = gsl_vector_get(s->x, i);
+        }
+    }
+
+    // Calculate the chi-squared for the derived solution.
+    *chiSq = gsl_blas_dnrm2(s->f);
+
+    // Free all allocated memory
+    // NOTE: Free x.
+    gsl_multifit_fdfsolver_free(s);
+    psFree(xInit);
+
+    // Bye bye.
+    return (initialGuess);
+}
+
+/******************************************************************************
+    This routine must fit a polynomial of degree myPoly to the data points
+    (x, y) and return the coefficients of that polynomial, as well as the
+    error for each data point (yErr).
+ 
+NOTE: yErr is currently ignored.
+ *****************************************************************************/
+psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* myPoly,
+                                        const psVector* restrict x,
+                                        const psVector* restrict y, const psVector* restrict yErr)
+{
+    int polyOrder = myPoly->n;
+    psImage* A = NULL;
+    psImage* ALUD = NULL;
+    psVector* B = NULL;
+    psVector* outPerm = NULL;
+    psVector* X = NULL;         // NOTE: do we need this?
+    psVector* coeffs = NULL;
+    int i = 0;
+    int j = 0;
+    int k = 0;
+    psVector* xSums = NULL;
+
+    // printf("psVectorFitPolynomial1D()\n");
+    // for (i=0;i<x->n;i++) {
+    // printf("(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]);
+    // }
+
+    PS_CHECK_NULL_1DPOLY(myPoly);
+    PS_CHECK_NULL_VECTOR(x);
+    PS_CHECK_EMPTY_VECTOR(x);
+    PS_CHECK_NULL_VECTOR(y);
+    PS_CHECK_EMPTY_VECTOR(y);
+    PS_CHECK_NULL_VECTOR(yErr);
+    PS_CHECK_EMPTY_VECTOR(yErr);
+    PS_CHECK_VECTOR_SIZE_EQUAL(x, y);
+    PS_CHECK_VECTOR_SIZE_EQUAL(y, yErr);
+
+    A = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
+    ALUD = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
+    B = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    coeffs = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    X = psVectorAlloc(x->n, PS_TYPE_F64);
+    outPerm = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    xSums = psVectorAlloc(1 + 2 * polyOrder, PS_TYPE_F64);
+
+    // Initialize data structures.
+    for (i = 0; i < (polyOrder); i++) {
+        B->data.F64[i] = 0.0;
+        coeffs->data.F64[i] = 0.0;
+        outPerm->data.F64[i] = 0.0;
+        for (j = 0; j < (polyOrder); j++) {
+            A->data.F64[i][j] = 0.0;
+            ALUD->data.F64[i][j] = 0.0;
+        }
+    }
+    for (i = 0; i < X->n; i++) {
+        X->data.F64[i] = x->data.F64[i];
+    }
+
+    // Build the B and A data structs.
+    for (i = 0; i < X->n; i++) {
+        p_psBuildSums1D(X->data.F64[i], 2 * polyOrder, xSums);
+
+        for (k = 0; k < (polyOrder); k++) {
+            B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k];
+        }
+
+        for (k = 0; k < (polyOrder); k++) {
+            for (j = 0; j < (polyOrder); j++) {
+                A->data.F64[k][j] += xSums->data.F64[k + j];
+            }
+        }
+    }
+
+    ALUD = psMatrixLUD(ALUD, outPerm, A);
+    coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+
+    for (k = 0; k < (polyOrder); k++) {
+        myPoly->coeff[k] = coeffs->data.F64[k];
+        // printf("myPoly->coeff[%d] is %f\n", k, myPoly->coeff[k]);
+    }
+
+    // for (i=0;i<x->n;i++) {
+    // printf("HMMM: psEvalPolynomial1D(%f) is %f\n", x->data.F64[i], psEvalPolynomial1D(x->data.F64[i],
+    // myPoly));
+    // }
+
+    psFree(A);
+    psFree(ALUD);
+    psFree(B);
+    psFree(coeffs);
+    psFree(X);
+    psFree(outPerm);
+    psFree(xSums);
+
+    return (myPoly);
+}
Index: /tags/rel2_1/psLib/src/dataManip/psMinimize.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psMinimize.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psMinimize.h	(revision 1553)
@@ -0,0 +1,105 @@
+#if !defined(PS_MINIMIZE_H)
+#define PS_MINIMIZE_H
+
+#include "psFunctions.h"
+
+/** \file psMinimize.h
+ *  \brief minimization operations
+ *  \ingroup Stats
+ */
+
+/** Functions **************************************************************/
+
+/** \addtogroup Stats
+ *  \{
+ */
+
+/** function of a collection of parameters and coordinate vector.
+ *
+ *  @return float    value to minimize
+ */
+typedef float (*psMinimizeFunction)(
+    const psVector* restrict params,   ///< collection of parameters
+    const psVector* restrict coord     ///< coordinates
+);
+
+/** derivative function of psMinimizeFunction
+ *
+ *  @return float     the derivative in respect to params[derivParam]
+ */
+typedef float (*psMinimizeFunctionDeriv) (
+    const psVector* restrict params,   ///< collection of parameters
+    const psVector* restrict coord,    ///< coordinates
+    int derivParam                     ///< index of parameter to calculate derivative of
+);
+
+/** Minimizes a non-linear function.
+ *
+ *  psMinimize determines and returns the vector that minimizes the specified 
+ *  function. It takes as input a function, myFunction, an initial guess for
+ *  the vector that minimizes the function, initialGuess, the current 
+ *  coordiate coord, and an optional mask for the vector elements (function 
+ *  parameters) to minimize, paramMask (all parameters are fit if PSLib SDRS 
+ *  25 July 13, 2004 Pan-STARRS Image Processing Pipeline PSDC-430-007-04 
+ *  NULL). Note that paramMask must be of type psU8, while params must be of 
+ *  type psF32. The optional function, myFuncDeriv returns the derivative of 
+ *  the function. This function must be valid only for types psF32, psF64.
+ *
+ *  @return psVector*    minimized vector
+ */
+psVector* psMinimize(
+    psVector* restrict initialGuess,
+    psMinimizeFunction myFunction,
+    psMinimizeFunctionDeriv myFunctionDeriv,
+    const psVector* restrict coord,
+    const psVector* restrict paramMask
+);
+
+/** Minimize chi^2 for input data.
+ *
+ *  psMinimizeChi2 fits a model to observations by minimizing chi^2, returning 
+ *  the best-fit parameters. The input parameters are a function that 
+ *  evaluates the model for a specified domain, given the parameters, 
+ *  evalModel; a list of observations, (domain, data, and errors); an initial 
+ *  guess at the best-fit parameters, initialGuess which is returned with the 
+ *  best-fit parameters, and an optional mask specifying which parameters are 
+ *  to be fit, paramMask, which must be of type psU8. All parameters are fit 
+ *  if this vector is NULL. This function must be valid only for types psF32, 
+ *  psF64.
+ *
+ *  @return psVector*      minimized vector
+ */
+psVector* psMinimizeChi2(
+    psMinimizeFunction evalModel,      ///< Model to fit; (domain and params)
+    psMinimizeFunctionDeriv DevalModel,///< Derivative of model to fit; (domain and params)
+    const psImage* restrict domain,    ///< The domain values for the corresponding measurements
+    const psVector* restrict data,     ///< Data to fit
+    const psVector* restrict errors,   ///< Errors in the data
+    psVector* restrict initialGuess,   ///< Initial guess
+    const psVector* restrict paramMask,///< 1 = fit for parameter, 0 = hold parameter constant
+    float *chiSq                       ///< chi squared
+);
+
+/** Derive a polynomial fit by chi^2 minimisation (analytically)
+ *
+ *  psVectorFitPolynomial1d returns the polynomial that best fits the 
+ *  observations. The input parameters are a polynomial that specifies the 
+ *  fit order, myPoly, which will be altered and returned with the best-fit 
+ *  coefficients; and the observations, x, y and yErr. The independent 
+ *  variable list, x may be NULL, in which case the vector index is used. 
+ *  The dependent variable error, yErr may be null, in which case the solution 
+ *  is determined in the assumption that all data errors are equal. This 
+ *  function must be valid only for types psF32, psF64.
+ *
+ *  @return psPolynomial1D*    polynomial fit
+ */
+psPolynomial1D* psVectorFitPolynomial1D(
+    psPolynomial1D* myPoly,            ///< Polynomial to fit
+    const psVector* restrict x,        ///< Ordinates (or NULL to just use the indices)
+    const psVector* restrict y,        ///< Coordinates
+    const psVector* restrict yErr      ///< Errors in coordinates, or NULL
+);
+
+/* \} */// End of MathGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psStats.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psStats.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psStats.c	(revision 1553)
@@ -0,0 +1,1888 @@
+
+/** @file  psStats.c
+ *  \brief basic statistical operations
+ *  @ingroup Stats
+ *
+ *  This file will hold the definition of the histogram and stats data
+ *  structures.  It also contains prototypes for procedures which operate
+ *  on those data structures.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+/*****************************************************************************/
+
+/* INCLUDE FILES                                                             */
+
+/*****************************************************************************/
+#include "psMemory.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psStats.h"
+#include "psMinimize.h"
+#include "psFunctions.h"
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+// will use robust statistical methods.
+#define GAUSS_WIDTH 20                     // The width of the Gaussian or boxcar smoothing.
+#define CLIPPED_NUM_ITER_LB 1
+#define CLIPPED_NUM_ITER_UB 10
+#define CLIPPED_SIGMA_LB 1.0
+#define CLIPPED_SIGMA_UB 10.0
+#define true 1
+#define false 0
+#define MY_MAX_FLOAT HUGE
+#define MAX_ITERATIONS 10
+
+void p_psVectorRobustStats(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats);
+
+/** Preprocessor macro to generate error on an incorrect type */
+#define PS_CHECK_VECTOR_TYPE(NAME, TYPE) \
+if (NAME->type.type != TYPE) { \
+    psError(__func__,"Invalid operation: %s has incorrect type.", #NAME); \
+}
+
+/** Preprocessor macro to generate error on a NULL vector */
+#define PS_CHECK_NULL_VECTOR(NAME) \
+if (NAME == NULL || NAME->data.V == NULL) { \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME); \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_EMPTY_VECTOR(NAME) \
+if (NAME->n < 1) { \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME); \
+}
+
+/** Preprocessor macro to generate error on differing size vectors */
+#define PS_CHECK_VECTOR_SIZE_EQUAL(VEC1, VEC2) \
+if (VEC1->n != VEC2->n) { \
+    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
+}
+
+#define PS_PRINT_VECTOR(NAME) \
+for (int my_i=0;my_i<NAME->n;my_i++) { \
+    printf("%s->data.F32[%d] is %f\n", #NAME, my_i, NAME->data.F32[my_i]); \
+} \
+printf("\n"); \
+
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+bool p_psGetStatValue(const psStats* stats, double *value)
+{
+
+    switch (stats->options & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE | PS_STAT_ROBUST_FOR_SAMPLE)) {
+    case PS_STAT_SAMPLE_MEAN:
+        *value = stats->sampleMean;
+        return true;
+
+    case PS_STAT_SAMPLE_MEDIAN:
+        *value = stats->sampleMedian;
+        return true;
+
+    case PS_STAT_SAMPLE_STDEV:
+        *value = stats->sampleStdev;
+        return true;
+
+    case PS_STAT_ROBUST_MEAN:
+        *value = stats->robustMean;
+        return true;
+
+    case PS_STAT_ROBUST_MEDIAN:
+        *value = stats->robustMedian;
+        return true;
+
+    case PS_STAT_ROBUST_MODE:
+        *value = stats->robustMode;
+        return true;
+
+    case PS_STAT_ROBUST_STDEV:
+        *value = stats->robustStdev;
+        return true;
+
+    case PS_STAT_CLIPPED_MEAN:
+        *value = stats->clippedMean;
+        return true;
+
+    case PS_STAT_CLIPPED_STDEV:
+        *value = stats->clippedStdev;
+        return true;
+
+    case PS_STAT_MAX:
+        *value = stats->max;
+        return true;
+
+    case PS_STAT_MIN:
+        *value = stats->min;
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+/*****************************************************************************
+p_psVectorPrint(myVector, maskVector, maskVal, stats): a private internal
+function that simply prints a vector to STDOUT.  Used primarily for
+debugging.
+ *****************************************************************************/
+
+void p_psVectorPrint(psVector* myVector, psVector* maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable.
+
+    for (i = 0; i < myVector->n; i++) {
+        if (maskVector != NULL)
+            printf("Element %d is %f (mask is %d)\n", i, myVector->data.F32[i], maskVector->data.U8[i]);
+        else
+            printf("Element %d is %f\n", i, myVector->data.F32[i]);
+    }
+}
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+    MISC PRIVATE STATISTICAL FUNCTIONS
+ 
+    NOTE: it is assumed that any call to these statistical functions will
+    have been preceded by a call to the psVectorStats() function.  Various
+    sanity tests will only be performed in psVectorStats().
+        Is the mask vector the same length as the data vector?
+        Is the mask vector of type PS_TYPE_U8?
+        Is the stats data structure NULL?
+        Is the in data structure NULL?
+        Is the in data structure of type PS_TYPE_F32?
+ ******************************************************************************
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+p_psVectorSampleMean(myVector, maskVector, maskVal, stats): calculates the
+mean of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ASSUMPTION: the mean is always calculated exactly.  Robust means are never
+calculated in this routine.
+ *****************************************************************************/
+
+void p_psVectorSampleMean(const psVector* restrict myVector,
+                          const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float mean = 0.0;           // The mean
+    int count = 0;              // # of points in this mean?
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // If PS_STAT_USE_RANGE is requested, then we enter a slightly different
+    // loop.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                // Check if the data is with the specified range
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                mean += myVector->data.F32[i];
+            }
+            mean /= (float)myVector->n;
+        }
+    }
+
+    stats->sampleMean = mean;
+}
+
+/******************************************************************************
+p_psVectorSampleMax(myVector, maskVector, maskVal, stats): calculates the
+max of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorMax(const psVector* restrict myVector,
+                   const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float max = -MY_MAX_FLOAT;  // The calculated maximum
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // If PS_STAT_USE_RANGE is requested, then we enter a different loop.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if ((myVector->data.F32[i] > max) &&
+                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                        max = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((myVector->data.F32[i] > max) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    max = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if (myVector->data.F32[i] > max) {
+                        max = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if (myVector->data.F32[i] > max) {
+                    max = myVector->data.F32[i];
+                }
+            }
+        }
+    }
+
+    stats->max = max;
+}
+
+/******************************************************************************
+p_psVectorSampleMin(myVector, maskVector, maskVal, stats): calculates the
+minimum of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorMin(const psVector* restrict myVector,
+                   const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float min = MY_MAX_FLOAT;   // The calculated maximum
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if ((myVector->data.F32[i] < min) &&
+                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                        min = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((myVector->data.F32[i] < min) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    min = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if (myVector->data.F32[i] < min) {
+                        min = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if (myVector->data.F32[i] < min) {
+                    min = myVector->data.F32[i];
+                }
+            }
+        }
+    }
+
+    stats->min = min;
+}
+
+/******************************************************************************
+p_psVectorNValues(myVector, maskVector, maskVal, stats): calculates the
+number of non-masked pixels in the vector that fall within the min/max
+range, if given.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+int p_psVectorNValues(const psVector* restrict myVector,
+                      const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int numData = 0;            // The number of data points
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    numData++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    numData++;
+                }
+            }
+        }
+    } else {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    numData++;
+                }
+            }
+        } else {
+            numData = myVector->n;
+        }
+    }
+    return (numData);
+}
+
+/******************************************************************************
+p_psVectorSampleMedian(myVector, maskVector, maskVal, stats): calculates the
+median of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorSampleMedian(const psVector* restrict myVector,
+                            const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psVector* unsortedVector = NULL;    // Temporary vector
+    psVector* sortedVector = NULL;      // Temporary vector
+    int i = 0;                  // Loop index variable
+    int count = 0;              // # of points in this mean?
+    int nValues = 0;            // # of points in vector
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // Determine if the number of data points exceed a threshold which will
+    // cause to generate robust stats, as opposed to exact stats.
+    // XXX: This code is no longer used.  We now calculate the median exactly
+    // regardless of the vector size.
+    /*
+     * if (myVector->n > stats->sampleLimit) { psAbort(__func__, "Robust Statistic Algorithms have not yet
+     * been defined or implemented.");
+     * 
+     * // Calculate the robust quartiles. stats2 = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
+     * p_psVectorRobustStats(myVector, maskVector, maskVal, stats2);
+     * 
+     * // Store the robust quartiles into the sample quartile members. stats->sampleMedian =
+     * stats2->robustMedian;
+     * 
+     * // Free temporary data buffers. psFree(stats2);
+     * 
+     * // Set the PS_STAT_ROBUST_FOR_SAMPLE bit in the stats structure. stats->options = stats->options |
+     * PS_STAT_ROBUST_FOR_SAMPLE;
+     * 
+     * return; } */
+
+    // Determine how many data points fit inside this min/max range
+    // and are not masked, IF the maskVector is not NULL>
+    nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats);
+
+    // Allocate temporary vectors for the data.
+    unsortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    unsortedVector->n = unsortedVector->nalloc;
+
+    sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    sortedVector->n = sortedVector->nalloc;
+
+    // Determine if we must only use data points within a min/max range.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+
+        // Store all non-masked data points within the min/max range
+        // into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = maskVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        // Store all non-masked data points into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                unsortedVector->data.F32[i] = myVector->data.F32[i];
+            }
+        }
+    }
+    // Sort the temporary vectors.
+    psVectorSort(sortedVector, unsortedVector);
+
+    // Calculate the median exactly.
+    // XXX: Is this the correct action?
+    if (0 == (nValues % 2)) {
+        stats->sampleMedian = 0.5 * (sortedVector->data.F32[(nValues / 2) - 1] +
+                                     sortedVector->data.F32[nValues / 2]);
+    } else {
+        stats->sampleMedian = sortedVector->data.F32[nValues / 2];
+    }
+
+    // Free the temporary data structures.
+    psFree(unsortedVector);
+    psFree(sortedVector);
+}
+
+/******************************************************************************
+    This routine smoothes the data in the input robustHistogram with a
+    Gaussian of width sigma.
+ 
+    XXX: Must consult with IfA on the proper values for the Gaussian
+    smoothing.  Currently, the Gaussian coefficients are such that only
+    the center coefficient is non-zero.  This is because "e" is being
+    raised to a very large negative number for all points except the
+    center point.
+ 
+    XXX: use a static variable for gaussianCoefs[] and compute them once.
+ *****************************************************************************/
+psVector* p_psVectorsmoothHistGaussian(psHistogram* robustHistogram, float sigma)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float denom = 0.0;          // Temporary variable
+    float expo = 0.0;           // Temporary variable
+    float gaussianCoefs[1 + (2 * GAUSS_WIDTH)]; // The Gaussian Coefficients
+    psVector* smooth = psVectorAlloc(robustHistogram->nums->n, PS_TYPE_F32);
+
+    for (i = 0; i < (1 + (2 * GAUSS_WIDTH)); i++) {
+        if (fabs(sigma) >= FLT_EPSILON) {
+            // If sigma does not equal zero, then we use Gaussian smoothing.
+            #ifdef  DARWIN
+            denom = (float)sqrt(2.0 * M_PI * sigma * sigma);
+            #else
+
+            denom = sqrtf(2.0 * M_PI * sigma * sigma);
+            #endif
+
+            expo = -(float)((i - GAUSS_WIDTH) * (i - GAUSS_WIDTH));
+            expo /= (2.0 * sigma * sigma);
+            gaussianCoefs[i] = exp(expo / denom);
+
+            // NOTE: Gaussian smoothing just isn't working with low sigma
+            // values.  The problem is that the Gaussian coefficients are
+            // all zero, except for the middle coefficient, which is exactly
+            // one.  Therefore, I'm using boxcar smoothing.
+            gaussianCoefs[i] = 1.0 / (1.0 + (2.0 * (float)GAUSS_WIDTH));
+            // printf("gaussianCoefs[%d] is %f\n", i, gaussianCoefs[i]);
+        } else {
+            /* If sigma equals zero (all pixels have the same value) the above code will divide by zero.
+             * Therefore, we don't need to smooth the data. */
+            for (i = 0; i < robustHistogram->nums->n; i++) {
+                smooth->data.F32[i] = (float)robustHistogram->nums->data.S32[i];
+            }
+            return (smooth);
+        }
+    }
+
+    // Perform the actual smoothing.
+    for (i = 0; i < robustHistogram->nums->n; i++) {
+        smooth->data.F32[i] = 0.0;
+        for (j = -GAUSS_WIDTH; j <= +GAUSS_WIDTH; j++) {
+            if (((j + i) >= 0) && ((j + i) < smooth->n)) {
+                smooth->data.F32[i] += (gaussianCoefs[j + GAUSS_WIDTH] *
+                                        (float)robustHistogram->nums->data.S32[j + i]);
+            }
+        }
+    }
+    return (smooth);
+}
+
+/******************************************************************************
+p_psVectorSampleQuartiles(myVector, maskVector, maskVal, stats): calculates
+the upper and/or lower quartiles of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorSampleQuartiles(const psVector* restrict myVector,
+                               const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psVector* unsortedVector = NULL;    // Temporary vector
+    psVector* sortedVector = NULL;      // Temporary vector
+    int i = 0;                  // Loop index variable
+    int count = 0;              // # of points in this mean?
+    int nValues = 0;            // # data points
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // Determine how many data points fit inside this min/max range
+    // and are not maxed, IF the maskVector is not NULL>
+    nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats);
+
+    // Allocate temporary vectors for the data.
+    unsortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    unsortedVector->n = unsortedVector->nalloc;
+    sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    sortedVector->n = sortedVector->nalloc;
+
+    // Determine if we must only use data points within a min/max range.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        // Store all non-masked data points within the min/max range
+        // into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        // Store all non-masked data points into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                unsortedVector->data.F32[i] = myVector->data.F32[i];
+            }
+        }
+    }
+
+    // Sort the temporary vectors.
+    psVectorSort(sortedVector, unsortedVector);
+
+    // Calculate the quartile points exactly.
+    stats->sampleUQ = sortedVector->data.F32[3 * (nValues / 4)];
+    stats->sampleLQ = sortedVector->data.F32[nValues / 4];
+
+    // Free the temporary data structures.
+    psFree(unsortedVector);
+    psFree(sortedVector);
+}
+
+/******************************************************************************
+p_psVectorSampleStdev(myVector, maskVector, maskVal, stats): calculates the
+stdev of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ 
+ *****************************************************************************/
+void p_psVectorSampleStdev(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int countInt = 0;           // # of data points being used
+    float countFloat = 0.0;     // # of data points being used
+    float mean = 0.0;           // The mean
+    float diff = 0.0;           // Used in calculating stdev
+    float sumSquares = 0.0;     // temporary variable
+    float sumDiffs = 0.0;       // temporary variable
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call p_psVectorSampleMean()
+    if (0 != isnan(stats->sampleMean)) {
+        p_psVectorSampleMean(myVector, maskVector, maskVal, stats);
+    }
+    mean = stats->sampleMean;
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+            countInt = myVector->n;
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                diff = myVector->data.F32[i] - mean;
+                sumSquares += (diff * diff);
+                sumDiffs += diff;
+                countInt++;
+            }
+            countInt = myVector->n;
+        }
+    }
+    countFloat = (float)countInt;
+
+    #ifdef DARWIN
+
+    stats->sampleStdev = (float)sqrt((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+    #else
+
+    stats->sampleStdev = sqrtf((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+    #endif
+}
+
+/******************************************************************************
+p_psVectorClippedStats(myVector, maskVector, maskVal, stats): calculates the
+clipped stats (mean or stdev) of the input vector.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorClippedStats(const psVector* restrict myVector,
+                            const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float clippedMean = 0.0;    // self-explanatory
+    float clippedStdev = 0.0;   // self-explanatory
+    float oldStanMean = 0.0;    // Temporary variable
+    float oldStanStdev = 0.0;   // Temporary variable
+    psVector* tmpMask = NULL;   // Temporary vector
+
+    // Endure that stats->clipIter is within the proper range.
+    if (!((CLIPPED_NUM_ITER_LB <= stats->clipIter) && (stats->clipIter <= CLIPPED_NUM_ITER_UB))) {
+        psAbort(__func__, "Unallowed value for clipIter (%d).\n", stats->clipIter);
+    }
+    // Endure that stats->clipSigma is within the proper range.
+    if (!((CLIPPED_SIGMA_LB <= stats->clipSigma) && (stats->clipSigma <= CLIPPED_SIGMA_UB))) {
+        psAbort(__func__, "Unallowed value for clipSigma (%f).\n", stats->clipSigma);
+    }
+    // We allocate a temporary mask vector since during the iterative
+    // steps that follow, we will be masking off additional data points.
+    // However, we do no want to modify the original mask vector.
+    tmpMask = psVectorAlloc(myVector->n, PS_TYPE_U8);
+    tmpMask->n = myVector->n;
+
+    // If we were called with a mask vector, then initialize the temporary
+    // mask vector with those values.
+    if (maskVector != NULL) {
+        for (i = 0; i < tmpMask->n; i++) {
+            tmpMask->data.U8[i] = maskVector->data.U8[i];
+        }
+    }
+    // 1. Compute the sample median.
+    // NOTE: This seems odd.  Verify with IfA that we want to calculate the
+    // median here, not the mean.
+    p_psVectorSampleMedian(myVector, maskVector, maskVal, stats);
+
+    // 2. Compute the sample standard deviation.
+    p_psVectorSampleStdev(myVector, maskVector, maskVal, stats);
+
+    // 3. Use the sample median as the first estimator of the mean X.
+    clippedMean = stats->sampleMean;
+
+    // 4. Use the sample stdev as the first estimator of the mean stdev.
+    clippedStdev = stats->sampleStdev;
+
+    // Must save the old sampleMean and sampleStdev since the following code
+    // block overwrites them.
+    oldStanMean = stats->sampleMean;
+    oldStanStdev = stats->sampleStdev;
+
+    // 5. Repeat N times:
+    for (i = 0; i < stats->clipIter; i++) {
+        for (j = 0; j < myVector->n; j++) {
+            // a) Exclude all values x_i for which |x_i - x| > K * stdev
+            if (fabs(myVector->data.F32[j] - clippedMean) > (stats->clipSigma * clippedStdev)) {
+                tmpMask->data.U8[i] = 0xff;
+            }
+            // b) compute new mean and stdev
+            p_psVectorSampleMedian(myVector, tmpMask, maskVal, stats);
+            p_psVectorSampleStdev(myVector, tmpMask, maskVal, stats);
+
+            // c) Use the new mean for x
+            clippedMean = stats->sampleMean;
+
+            // d) Use the new stdev for stdev
+            clippedStdev = stats->sampleStdev;
+        }
+
+    }
+    stats->sampleMean = oldStanMean;
+    stats->sampleStdev = oldStanStdev;
+
+    // 7. The last calcuated value of x is the cliped mean.
+    if (stats->options & PS_STAT_CLIPPED_MEAN) {
+        stats->clippedMean = clippedMean;
+    }
+    // 8. The last calcuated value of stdev is the cliped stdev.
+    if (stats->options & PS_STAT_CLIPPED_STDEV) {
+        stats->clippedStdev = clippedStdev;
+    }
+
+    psFree(tmpMask);
+}
+
+/*****************************************************************************
+p_psNormalizeVector(myData): this is a private function which normalizes the
+elements of a vector to a range between 0.0 and 1.0.
+ *****************************************************************************/
+void p_psNormalizeVector(psVector* myData)
+{
+    float min = (float)HUGE;
+    float max = (float)-HUGE;
+    float range = 0.0;
+    int i = 0;
+
+    for (i = 0; i < myData->n; i++) {
+        if (myData->data.F32[i] < min) {
+            min = myData->data.F32[i];
+        }
+        if (myData->data.F32[i] > max) {
+            max = myData->data.F32[i];
+        }
+    }
+
+    range = max - min;
+    for (i = 0; i < myData->n; i++) {
+        myData->data.F32[i] = (myData->data.F32[i] - min) / range;
+    }
+}
+
+/*****************************************************************************
+p_psGaussian(myData, myParams): an internal function, used by robust stats,
+intended to compute the Gaussian with a specified sigma/mean, at the
+specified data point.
+ *****************************************************************************/
+float p_psGaussian(const psVector* restrict myData, const psVector* restrict myParams)
+{
+    float x = myData->data.F32[0];
+    float mean = myParams->data.F32[0];
+    float stdev = myParams->data.F32[1];
+    float tmp = exp(-((x - mean) * (x - mean)) / (2.0 * stdev * stdev));
+
+    tmp /= ((float)sqrt(2.0 * M_PI * (stdev * stdev)));
+
+    // printf("p_psGaussian((%.2f), %.2f, %.2f) is %.2f\n", x, mean, stdev, tmp);
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psGaussianDeriv(myData, myParams, whichParam): an internal function, which
+calculates the specified partial derivative of the above Gaussian function.
+ *****************************************************************************/
+float p_psGaussianDeriv(const psVector* restrict myData, const psVector* restrict myParams, int whichParam)
+{
+    float x = myData->data.F32[0];
+    float mean = myParams->data.F32[0];
+    float stdev = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParam == 0) {
+        // Return the derivative w.r.t. the mean.
+        tmp = (x - mean) * p_psGaussian(myData, myParams);
+        tmp /= (stdev * stdev);
+    } else if (whichParam == 1) {
+        // Return the derivative w.r.t. the stdev.
+        tmp = (x - mean) * (x - mean) * p_psGaussian(myData, myParams);
+        tmp /= (stdev * stdev * stdev);
+    }
+    printf("p_psGaussianDeriv((%.2f), %.2f, %.2f, (%d)) is %.2f\n", x, mean, stdev, whichParam, tmp);
+
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psQuadratic(myData, myParams): an internal function, used by robust stats,
+intended to compute a quadratic, with the specified parameters, at the
+specified data point.
+ *****************************************************************************/
+float p_psQuadratic(const psVector* restrict myParams, const psVector* restrict myCoords)
+{
+    float x = myCoords->data.F32[0];
+    float A = myParams->data.F32[0];
+    float B = myParams->data.F32[1];
+    float C = myParams->data.F32[2];
+    float tmp = 0.0;
+
+    tmp = (A * x * x) + (B * x) + C;
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psQuadraticDeriv(myData, myParams, whichParam): an internal function, which
+calculates the specified partial derivative of the above quadratic function.
+ *****************************************************************************/
+float p_psQuadraticDeriv(const psVector* restrict myParams,
+                         const psVector* restrict myCoords, int whichParamDeriv)
+{
+    float x = myCoords->data.F32[0];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = x * x;
+    } else if (whichParamDeriv == 1) {
+        tmp = x;
+    } else if (whichParamDeriv == 2) {
+        tmp = 1.0;
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+p_ps1DPolyMedian(myPoly, rangeLow, rangeHigh, midpoint): This routine takes
+as input a 1-D polynomial of arbitrary order (though we are using 2nd-order
+polynomials here) and a range of x-values for which it is defined:
+[rangeLow, rangeHigh].  It determines the x-value of that polynomial such
+that f(x) == midpoint.  This functions uses a binary-search algorithm on the
+range and assumes that the polynomial is monotonically increasing or
+decreasing within that range.
+ *****************************************************************************/
+float p_ps1DPolyMedian(psPolynomial1D* myPoly, float rangeLow, float rangeHigh, float getThisValue)
+{
+    int numIterations = 0;
+    float midpoint = 0.0;
+    float oldMidpoint = 1.0;
+    float f = 0.0;
+
+    // printf("p_ps1DPolyMedian(%f, %f, %f) \n", rangeLow, rangeHigh, getThisValue);
+
+    while (numIterations < MAX_ITERATIONS) {
+        midpoint = (rangeHigh + rangeLow) / 2.0;
+        if (fabs(midpoint - oldMidpoint) <= FLT_EPSILON) {
+            return (midpoint);
+        }
+        oldMidpoint = midpoint;
+
+        f = psPolynomial1DEval(midpoint, myPoly);
+        // printf("p_ps1DPolyMedian() iteration %d.  f(%f) is %f\n", numIterations, midpoint, f);
+        if (fabs(f - getThisValue) <= FLT_EPSILON) {
+            return (midpoint);
+        }
+
+        if (f > getThisValue) {
+            rangeHigh = midpoint;
+        } else {
+            rangeLow = midpoint;
+        }
+        numIterations++;
+    }
+    return (midpoint);
+}
+
+/******************************************************************************
+p_psFitQuadratic(robustHistogram. cumulativeSums, binNum, fitFloat): given
+the specified histogram, with the specified pre-calculated cumulativeSums,
+this routine fits a quadratic f(x) to the 3 bins surrounding bin "binNum",
+and then finds the point x such that f(x) == fitFloat.
+ 
+XXX: This function is currently not being used.
+ *****************************************************************************/
+float p_psFitQuadratic(psHistogram* histogram, psVector* cumulativeSums, int binNum, float fitFloat)
+{
+    psVector* x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* y = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* yErr = psVectorAlloc(3, PS_TYPE_F64);
+    psPolynomial1D* myPoly = psPolynomial1DAlloc(2);
+
+    if ((binNum > 0) && (binNum < (histogram->nums->n + 1))) {
+        x->data.F64[0] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum - 1] + histogram->bounds->data.F32[binNum]);
+        x->data.F64[1] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum] + histogram->bounds->data.F32[binNum + 1]);
+        x->data.F64[2] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum + 1] + histogram->bounds->data.F32[binNum + 2]);
+
+        y->data.F64[0] = cumulativeSums->data.F32[binNum - 1];
+        y->data.F64[1] = cumulativeSums->data.F32[binNum];
+        y->data.F64[2] = cumulativeSums->data.F32[binNum + 1];
+
+        if (!((y->data.F64[0] <= fitFloat) && (fitFloat <= y->data.F64[2]))) {
+            psAbort(__func__, "p_psVectorRobustStats(0): midpoint not within y-range\n");
+        }
+
+        yErr->data.F64[0] = 1.0;
+        yErr->data.F64[1] = 1.0;
+        yErr->data.F64[2] = 1.0;
+
+        myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+        return (p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], fitFloat));
+    } else {
+        return (0.5 * (histogram->bounds->data.F32[binNum + 1] + histogram->bounds->data.F32[binNum]));
+    }
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(myPoly);
+    return (0.0);
+}
+
+/******************************************************************************
+p_psVectorRobustStats(myVector, maskVector, maskVal, stats): this procedure
+calculates a variety of robust stat measures:
+    PS_STAT_ROBUST_MEAN
+    PS_STAT_ROBUST_MEDIAN
+    PS_STAT_ROBUST_MODE
+    PS_STAT_ROBUST_STDEV
+    PS_STAT_ROBUST_QUARTILE
+I have included all that computation in a single function, as opposed to
+breaking it across several functions for one primary reason:  they all
+require the same basic initial processing steps (calculate the histogram,
+etc.)  however there is no currently defined means, in the SDRS, to specify
+this computation as a separate step.  If the above robust stat measures were
+calcualted in separate functiosn, then much of the initial processing would
+be duplicated.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+*****************************************************************************/
+void p_psVectorRobustStats(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psHistogram* robustHistogram = NULL;
+    psVector* robustHistogramVector = NULL;
+    float binSize = 0.0;        // Size of the histogram bins
+    int LQBinNum = -1;          // Bin num for lower quartile
+    int UQBinNum = -1;          // Bin num for upper quartile
+    int i = 0;                  // Loop index variable
+    int maxBinNum = 0;
+    float maxBinCount = 0.0;
+    float dL = 0.0;
+    int numBins = 0;
+    psStats* tmpStats = psStatsAlloc(PS_STAT_CLIPPED_STDEV | PS_STAT_CLIPPED_MEAN);
+
+    // psImage* domain;
+    // psVector* errors;
+    // psVector* data;
+    // psVector* initialGuess;
+    // psVector* theParams;
+    // float chiSq=0.0;
+    // float max = -HUGE;
+    // float max_pos;
+    float myMean = 0.0;
+    float myStdev = 0.0;
+    float countFloat = 0.0;
+    float diff = 0.0;
+    float sumSquares = 0.0;
+    float sumDiffs = 0.0;
+    psVector* x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* y = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* yErr = psVectorAlloc(3, PS_TYPE_F64);
+    psPolynomial1D* myPoly = psPolynomial1DAlloc(2);
+    psVector* cumulativeRobustSumsFullRange = NULL;
+    psVector* cumulativeRobustSumsDlRange = NULL;
+    float sumRobust = 0.0;
+    float sumN50 = 0.0;
+    float sumNfit = 0.0;
+    float cumulativeMedian = 0.0;
+
+    // Compute the initial bin size of the robust histogram.  This is done
+    // by computing the clipped standard deviation of the vector, and dividing
+    // that by 10.0;
+    p_psVectorClippedStats(myVector, maskVector, maskVal, tmpStats);
+    binSize = tmpStats->clippedStdev / 10.0f;
+
+    // If stats->clippedStdev == 0.0, then all data elements have the same
+    // value.  Therefore, we can set the appropiate results and return.
+    if (fabs(binSize) <= FLT_EPSILON) {
+        if (stats->options & PS_STAT_ROBUST_MEAN) {
+            stats->robustMean = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_MEDIAN) {
+            stats->robustMedian = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_MODE) {
+            stats->robustMode = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_STDEV) {
+            stats->robustStdev = 0.0;
+        }
+        if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+            stats->robustUQ = stats->clippedMean;
+            stats->robustLQ = stats->clippedMean;
+        }
+        // XXX: Set these to the number of unmasked data points?
+        stats->robustNfit = 0.0;
+        stats->robustN50 = 0.0;
+        psFree(tmpStats);
+        return;
+    }
+    // Determine minimum and maximum values in the data vector.
+    if (isnan(stats->min)) {
+        p_psVectorMin(myVector, maskVector, maskVal, stats);
+    }
+    if (isnan(stats->max)) {
+        p_psVectorMax(myVector, maskVector, maskVal, stats);
+    }
+    // Create the histogram structure.  NOTE: we can not specify the bin size
+    // precisely since the argument to psHistogramAlloc() is the number of
+    // bins, not the binSize.  Also, if we get here, we know that
+    // binSize != 0.0.
+    numBins = (int)((stats->max - stats->min) / binSize);
+    robustHistogram = psHistogramAlloc(stats->min, stats->max, numBins);
+
+    // Populate the histogram array.
+    psVectorHistogram(robustHistogram, myVector, maskVector, maskVal);
+
+    // Smooth the histogram.
+    // XXX: is that the right stdev?
+    robustHistogramVector = p_psVectorsmoothHistGaussian(robustHistogram, tmpStats->clippedStdev / 4.0f);
+
+    // The following was necessary to fit a gaussian to the data, since
+    // gaussian functions produce data between 0.0 and 1.0.
+    // p_psNormalizeVector(robustHistogramVector);
+
+    /**************************************************************************
+    Determine the lower/upper quartiles.
+    **************************************************************************/
+    // We define a vector called "cumulativeRobustSums..." where the value at
+    // index position i is equal to the sum of bins 0:i.  This will be used
+    // now and later in determining the lower/upper quartiles.
+    cumulativeRobustSumsFullRange = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    cumulativeRobustSumsFullRange->data.F32[0] = robustHistogramVector->data.F32[0];
+    for (i = 1; i < robustHistogramVector->n; i++) {
+        cumulativeRobustSumsFullRange->data.F32[i] =
+            cumulativeRobustSumsFullRange->data.F32[i - 1] + robustHistogramVector->data.F32[i];
+    }
+    sumRobust = cumulativeRobustSumsFullRange->data.F32[robustHistogramVector->n - 1];
+
+    // Determine the bin number containing the lower quartile point.
+    LQBinNum = -1;
+    for (i = 0; i < cumulativeRobustSumsFullRange->n; i++) {
+        if (cumulativeRobustSumsFullRange->data.F32[i] >= (sumRobust / 4.0)) {
+            LQBinNum = i;
+            break;
+        }
+    }
+
+    // Determine the bin number containing the upper quartile point.
+    UQBinNum = -1;
+    for (i = cumulativeRobustSumsFullRange->n - 1; i >= 0; i--) {
+        if (cumulativeRobustSumsFullRange->data.F32[i] <= (3.0 * sumRobust / 4.0)) {
+            UQBinNum = i;
+            break;
+        }
+    }
+
+    if ((LQBinNum == -1) || (UQBinNum == -1)) {
+        psAbort(__func__, "Could not determine the robust lower/upper quartiles.");
+    }
+
+    /**************************************************************************
+    Determine the mode in the range LQ:UQ.
+    **************************************************************************/
+    // Determine the bin with the peak value in the range LQ to UQ.
+    maxBinNum = LQBinNum;
+    maxBinCount = robustHistogramVector->data.F32[LQBinNum];
+    sumN50 = (float)robustHistogram->nums->data.S32[LQBinNum];
+    for (i = LQBinNum + 1; i <= UQBinNum; i++) {
+        if (robustHistogramVector->data.F32[i] > maxBinCount) {
+            maxBinNum = i;
+            maxBinCount = robustHistogramVector->data.F32[i];
+        }
+        sumN50 += (float)robustHistogram->nums->data.S32[i];
+    }
+
+    // XXX: is dL defined as the value at the LQ/UQ, or the bin number?
+    dL = (UQBinNum - LQBinNum) / 4;
+
+    printf("(LQBinNum, UQBinNum, maxBinNum) is (%d, %d, %d)\n", LQBinNum, UQBinNum, maxBinNum);
+
+    /**************************************************************************
+    Determine the mean/stdev for the bins in the range mode-dL to mode+dL
+    **************************************************************************/
+    cumulativeRobustSumsDlRange = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    for (i = 0; i < robustHistogramVector->n; i++) {
+        cumulativeRobustSumsDlRange->data.F32[i] = 0.0;
+    }
+    sumNfit = 0.0;
+    cumulativeMedian = 0.0;
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            cumulativeRobustSumsDlRange->data.F32[i] =
+                cumulativeRobustSumsDlRange->data.F32[i - 1] + robustHistogramVector->data.F32[i];
+            cumulativeMedian += robustHistogramVector->data.F32[i];
+            sumNfit += (float)robustHistogram->nums->data.S32[i];
+        }
+    }
+
+    // Calculate the mean of the smoothed robust histogram in the range
+    // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
+    // that bin (this is a non-exact approximation).
+    myMean = 0.0;
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            myMean += (robustHistogramVector->data.F32[i]) * 0.5 *
+                      (robustHistogram->bounds->data.F32[i + 1] + robustHistogram->bounds->data.F32[i]);
+            countFloat += robustHistogramVector->data.F32[i];
+        }
+    }
+    myMean /= countFloat;
+
+    // Calculate the stdev of the smoothed robust histogram in the range
+    // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
+    // that bin.
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            diff = (0.5 * (robustHistogram->bounds->data.F32[i + 1] +
+                           robustHistogram->bounds->data.F32[i])) - myMean;
+            sumSquares += diff * diff * robustHistogramVector->data.F32[i];
+            sumDiffs += diff * robustHistogramVector->data.F32[i];
+        }
+    }
+    myStdev = sqrt((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+
+    /**************************************************************************
+    Set the appropriate members in the output stats struct.
+    **************************************************************************/
+    if (stats->options & PS_STAT_ROBUST_MEAN) {
+        stats->robustMean = myMean;
+    }
+
+    if (stats->options & PS_STAT_ROBUST_MODE) {
+        stats->robustMode = 0.5 *
+                            (robustHistogram->bounds->data.F32[maxBinNum] + robustHistogram->bounds->data.F32[maxBinNum + 1]);
+    }
+
+    if (stats->options & PS_STAT_ROBUST_STDEV) {
+        stats->robustStdev = myStdev;
+    }
+    // To determine the median (and later, the lower/upper quartile), we fit
+    // a quadratic to the three bins surrounding the bin containing the median.
+    // The quadratic y=f(x) with x being the midpoint of each bin, and y being
+    // the cumulative number of data points in all bins up to, and including,
+    // this bin.  We then solve the quadratic for
+
+    if (stats->options & PS_STAT_ROBUST_MEDIAN) {
+        if ((maxBinNum > 0) && (maxBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum - 1] +
+                              robustHistogram->bounds->data.F32[maxBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum] +
+                              robustHistogram->bounds->data.F32[maxBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum + 1] +
+                              robustHistogram->bounds->data.F32[maxBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsDlRange->data.F32[maxBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsDlRange->data.F32[maxBinNum];
+            y->data.F64[2] = cumulativeRobustSumsDlRange->data.F32[maxBinNum + 1];
+
+            // Ensure that cumulativeMedian/2 is actually within the range of the bins
+            // we are using.
+            cumulativeMedian *= 0.5;
+            if (!((y->data.F64[0] <= cumulativeMedian) && (cumulativeMedian <= y->data.F64[2]))) {
+                printf("((%f), %f, %f)\n", cumulativeMedian, y->data.F64[0], y->data.F64[2]);
+                psAbort(__func__, "p_psVectorRobustStats(1): midpoint not within y-range\n");
+            }
+            // XXX: yErr is not currently used by psVectorFitPolynomial1D().  We
+            // may have to set this meaningfully later.
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            // Determine the coefficients of the polynomial.
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            // Call p_ps1DPolyMedian(), which does a binary search on the
+            // polynomial, looking for the value x such that
+            // f(x) = cumulativeMedian.
+            stats->robustMedian = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], cumulativeMedian);
+        } else {
+            // If the mode is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustMedian = 0.5 * (robustHistogram->bounds->data.F32[maxBinNum + 1] +
+                                         robustHistogram->bounds->data.F32[maxBinNum]);
+        }
+    }
+    // The lower/upper quartile calculations are very similar to the median
+    // calculations.  We fit a quadratic to the array containing the
+    // cumulative data points in each bin, then search for x such that
+    // f(x) equals the lower/upper quartile exactly.
+    //
+    if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+        countFloat = cumulativeRobustSumsFullRange->data.F32[robustHistogramVector->n - 1];
+
+        if ((LQBinNum > 0) && (LQBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum - 1] +
+                              robustHistogram->bounds->data.F32[LQBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum] +
+                              robustHistogram->bounds->data.F32[LQBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum + 1] +
+                              robustHistogram->bounds->data.F32[LQBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[LQBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[LQBinNum];
+            y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[LQBinNum + 1];
+
+            if (!((y->data.F64[0] <= (countFloat / 4.0)) && ((countFloat / 4.0) <= y->data.F64[2]))) {
+                psAbort(__func__, "p_psVectorRobustStats(2): midpoint not within y-range\n");
+            }
+
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            stats->robustLQ = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], countFloat / 4.0);
+
+        } else {
+            // If the LQ is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustLQ = 0.5 * (robustHistogram->bounds->data.F32[LQBinNum + 1] +
+                                     robustHistogram->bounds->data.F32[LQBinNum]);
+        }
+
+        if ((UQBinNum > 0) && (UQBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum - 1] +
+                              robustHistogram->bounds->data.F32[UQBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum] +
+                              robustHistogram->bounds->data.F32[UQBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum + 1] +
+                              robustHistogram->bounds->data.F32[UQBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[UQBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[UQBinNum];
+            y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[UQBinNum + 1];
+
+            if (!((y->data.F64[0] <= (3.0 * countFloat / 4.0)) &&
+                    ((3.0 * countFloat / 4.0) <= y->data.F64[2]))) {
+                psAbort(__func__, "p_psVectorRobustStats(3): midpoint not within y-range\n");
+            }
+
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            stats->robustUQ = p_ps1DPolyMedian(myPoly,
+                                               x->data.F64[0], x->data.F64[2], 3.0 * countFloat / 4.0);
+        } else {
+            // If the UQ is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustUQ = 0.5 * (robustHistogram->bounds->data.F32[UQBinNum + 1] +
+                                     robustHistogram->bounds->data.F32[UQBinNum]);
+        }
+    }
+    stats->robustNfit = sumNfit;
+    stats->robustN50 = sumN50;
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(tmpStats);
+    psFree(robustHistogram);
+    psFree(myPoly);
+    psFree(cumulativeRobustSumsFullRange);
+    psFree(cumulativeRobustSumsDlRange);
+}
+
+/*
+void p_ps_FitTheGaussian()
+{
+ 
+    // Fit a Gaussian to the bins in the range MODE-dL to Mode+dL
+    // NOTE: This code uses the psMinimize.c functions to perform
+    // the fit.  It doesn't quite work, 100% of the time.  For the time being
+    // I am commenting this code out, and replacing it with code which
+    // calculates the mean directly on the robustHistogram.
+ 
+    domain = psImageAlloc(1, robustHistogramVector->n, PS_TYPE_F32);
+    errors = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    data = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    initialGuess = psVectorAlloc(2, PS_TYPE_F32);
+ 
+    max = -HUGE;
+    max_pos = -1;
+    for (i=0;i<robustHistogramVector->n;i++) {
+        domain->data.F32[i][0] = 0.5 * (robustHistogram->bounds->data.F32[i+1] +
+                                        robustHistogram->bounds->data.F32[i]);
+        data->data.F32[i] = (float) robustHistogramVector->data.F32[i];
+        errors->data.F32[i] = 1.0;
+        //printf("DATA (%.2f, %.2f)\n", domain->data.F32[i][0], data->data.F32[i]);
+        if (data->data.F32[i] > max) {
+            max = data->data.F32[i];
+            max_pos = domain->data.F32[i][0];
+        }
+    }
+ 
+    initialGuess->data.F32[0] = max_pos;
+    initialGuess->data.F32[1] = 1.0;
+    printf("Initial (mean. stdev) is (%.3f, %.3f)\n", initialGuess->data.F32[0], initialGuess->data.F32[1]);
+ 
+    printf("Calling psMinimizeChi2()\n");
+    theParams = psMinimizeChi2(p_psGaussian,
+                               p_psGaussianDeriv,
+                               domain,
+                               data,
+                               errors,
+                               initialGuess,
+                               NULL,
+                               &chiSq);
+    printf("Called psMinimizeChi2()\n");
+    printf("p_psVectorRobustStats() is (%f, %f)\n", theParams->data.F32[0], theParams->data.F32[1]);
+}
+*/
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+static void histogramFree(psHistogram* myHist);
+
+/******************************************************************************
+    psStatsAlloc(): This routine must create a new psStats data structure.
+ *****************************************************************************/
+psStats* psStatsAlloc(psStatsOptions options)
+{
+    psStats* newStruct = NULL;
+
+    newStruct = (psStats* ) psAlloc(sizeof(psStats));
+    newStruct->sampleMean = NAN;
+    newStruct->sampleMedian = NAN;
+    newStruct->sampleStdev = NAN;
+    newStruct->sampleUQ = NAN;
+    newStruct->sampleLQ = NAN;
+    newStruct->sampleLimit = 30000;
+    newStruct->robustMean = NAN;
+    newStruct->robustMedian = NAN;
+    newStruct->robustMode = NAN;
+    newStruct->robustStdev = NAN;
+    newStruct->robustUQ = NAN;
+    newStruct->robustLQ = NAN;
+    newStruct->robustN50 = NAN;
+    newStruct->robustNfit = NAN;
+    newStruct->clippedMean = NAN;
+    newStruct->clippedStdev = NAN;
+    newStruct->clipSigma = 3.0;
+    newStruct->clipIter = 3.0;
+    newStruct->min = NAN;
+    newStruct->max = NAN;
+    newStruct->binsize = NAN;
+    newStruct->options = options;
+
+    return (newStruct);
+}
+
+/******************************************************************************
+psHistogramAlloc(lower, upper, n): allocate a uniform histogram structure
+with the specifed upper and lower limits, and the specifed number of bins.
+This routine will also set the bounds for each of the bins.
+ 
+Input:
+    lower
+    upper
+    n
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAlloc(float lower, float upper, int n)
+{
+    int i = 0;                  // Loop index variable
+    psHistogram* newHist = NULL;        // The new histogram structure
+    float binSize = 0.0;        // The histogram bin size
+
+    // NOTE: Verify that this is the correct action.
+    if (n == 0) {
+        return (NULL);
+    }
+    if (n < 0) {
+        psAbort(__func__, "psHistogramAlloc() called with bin size %d.\n", n);
+    }
+    // NOTE: Verify that this is the correct action.
+    if (lower > upper) {
+        return (NULL);
+    }
+    // Allocate memory for the new histogram structure.  If there are N
+    // bins, then there are N+1 bounds to those bins.
+    newHist = (psHistogram* ) psAlloc(sizeof(psHistogram));
+    p_psMemSetDeallocator(newHist, (psFreeFcn) histogramFree);
+    newHist->bounds = psVectorAlloc(n + 1, PS_TYPE_F32);
+    newHist->bounds->n = newHist->bounds->nalloc;
+
+    // Calculate the bounds for each bin.
+    binSize = (upper - lower) / (float)n;
+    // NOTE: Is the following necessary? It prevents the max data point
+    // from being in a non-existant bin.
+    binSize += FLT_EPSILON;
+    for (i = 0; i < n + 1; i++) {
+        newHist->bounds->data.F32[i] = lower + (binSize * (float)i);
+    }
+
+    // Allocate the bins, and initialize them to zero.
+    newHist->nums = psVectorAlloc(n, PS_TYPE_U32);
+    newHist->nums->n = newHist->nums->nalloc;
+    for (i = 0; i < newHist->nums->n; i++) {
+        newHist->nums->data.U32[i] = 0;
+    }
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = true;
+
+    return (newHist);
+}
+
+/******************************************************************************
+psHistogramAllocGenric(bounds): allocate a non-uniform histogram structure
+with the specifed bounds.
+ 
+Input:
+    bounds
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAllocGeneric(const psVector* restrict bounds)
+{
+    psHistogram* newHist = NULL;        // The new histogram structure
+    int i;                      // Loop index variable
+
+    // NOTE: Verify that this is the correct action.
+    if (bounds == NULL) {
+        // psAbort(__func__, "psHistogram requested with NULL bounds");
+        return (NULL);
+    }
+    // NOTE: Verify that this is the correct action.
+    if (bounds->n <= 1) {
+        // psAbort(__func__, "psHistogram requested with NULL bounds");
+        return (NULL);
+    }
+
+    if (bounds->type.type != PS_TYPE_F32) {
+        // psAbort(__func__, "psHistogram request a bound which is not type F32");
+        return (NULL);
+    }
+    // Allocate memory for the new histogram structure.
+    newHist = (psHistogram* ) psAlloc(sizeof(psHistogram));
+    p_psMemSetDeallocator(newHist, (psFreeFcn) histogramFree);
+    newHist->bounds = psVectorAlloc(bounds->n, PS_TYPE_F32);
+    newHist->bounds->n = newHist->bounds->nalloc;
+    for (i = 0; i < bounds->n; i++) {
+        newHist->bounds->data.F32[i] = bounds->data.F32[i];
+    }
+
+    // Allocate the bins, and initialize them to zero.  If there are N bounds,
+    // then there are N-1 bins.
+    newHist->nums = psVectorAlloc((bounds->n) - 1, PS_TYPE_U32);
+    newHist->nums->n = newHist->nums->nalloc;
+    for (i = 0; i < newHist->nums->n; i++) {
+        newHist->nums->data.U32[i] = 0;
+    }
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = false;
+
+    return (newHist);
+}
+
+static void histogramFree(psHistogram* myHist)
+{
+    psFree(myHist->bounds);
+    psFree(myHist->nums);
+}
+
+/*****************************************************************************
+psVectorHistogram(out, in, mask, maskVal): this procedure takes as input a
+preallocated and initialized histogram structure.  It fills the bins in that
+histogram structure in accordance with the input data "in" and the, possibly
+NULL, mask vector.
+ 
+Inputs:
+    out
+    in
+    mask
+    maskVal
+Returns:
+    The histogram structure "out".
+ *****************************************************************************/
+psHistogram* psVectorHistogram(psHistogram* out,
+                               const psVector* restrict in,
+                               const psVector* restrict mask, unsigned int maskVal)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float binSize = 0.0;        // Histogram bin size
+    int binNum = 0;             // A temporary bin number
+    int numBins = 0;            // The total number of bins
+
+    // NOTE: Verify that this is the correct action.
+    if (out == NULL) {
+        return (NULL);
+    }
+    // Check the specified output histogram for type psF32
+    if (out->bounds->type.type != PS_TYPE_F32) {
+        psAbort(__func__, "Only data type PS_TYPE_F32 for the output.bounds member.");
+    }
+
+    if (out->nums->type.type != PS_TYPE_U32) {
+        psAbort(__func__, "Only data type PS_TYPE_U32 for output.nums member.");
+    }
+    // NOTE: Verify that this is the correct action.
+    if (in == NULL) {
+        return (out);
+    }
+
+    if (in->type.type != PS_TYPE_F32) {
+        psAbort(__func__, "Only data type PS_TYPE_F32 is currently supported (0x%x).", in->type.type);
+    }
+
+    if (mask != NULL) {
+        if (in->n != mask->n) {
+            psAbort(__func__, "Vector data and vector mask are of different sizes.");
+        }
+        if (mask->type.type != PS_TYPE_U8) {
+            psAbort(__func__, "Vector mask must be type PS_TYPE_U8");
+        }
+    }
+    // NOTE: determine the correct action for a variety of other cases:
+    // in vector has 0 elements, and histogram structure has zero bins.
+
+    numBins = out->nums->n;
+    for (i = 0; i < in->n; i++) {
+        // Check if this pixel is masked, and if so, skip it.
+        if ((mask == NULL) || ((mask != NULL) && (!(mask->data.U8[i] & maskVal)))) {
+            // Check if this pixel is below the minimum value, and if so
+            // count it, then skip it.
+            if (in->data.F32[i] < out->bounds->data.F32[0]) {
+                out->minNum++;
+                // Check if this pixel is above the maximum value, and if so
+                // count it, then skip it.
+            } else if (in->data.F32[i] > out->bounds->data.F32[numBins]) {
+                out->maxNum++;
+            } else {
+                // If this is a uniform histogram, determining the correct
+                // number is trivial.
+                if (out->uniform == true) {
+                    binSize = out->bounds->data.F32[1] - out->bounds->data.F32[0];
+                    binNum = (int)((in->data.F32[i] - out->bounds->data.F32[0]) / binSize);
+
+                    // NOTE: This next if-statement really shouldn't be necessary.
+                    // However, do to numerical lack of precision, we occasionally
+                    // produce a binNum outside the range of bins.
+                    if (binNum >= out->nums->n) {
+                        binNum = out->nums->n - 1;
+                    }
+
+                    (out->nums->data.S32[binNum])++;
+
+                    // If this is a non-uniform histogram, determining the correct
+                    // bin number requires a bit more work.
+                } else {
+                    // NOTE: This is slow.  Put a smarter algorithm here to
+                    // find the correct bin number (bin search, probably)
+                    for (j = 0; j < (out->bounds->n) - 1; j++) {
+                        if ((out->bounds->data.S32[j] <= in->data.F32[i]) &&
+                                (in->data.F32[i] <= out->bounds->data.S32[j + 1])) {
+                            (out->nums->data.S32[j])++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return (out);
+}
+
+/******************************************************************************
+p_psConvertToF32(myVector, maskVector, maskVal, stats): this is the cheap
+way to support a variety of vector data types: we simply convert the input
+vector to F32 at the beginning, and write all of our functions in F32.  If
+the vast majority of all vector stat operations are F32 (or any other single
+type), then this is probably the best way to go.  Otherwise, when the
+algorithms stablize, we will then macro everything and put type support in
+the various stat functions.
+ *****************************************************************************/
+psVector* p_psConvertToF32(psStats* stats, psVector* in, psVector* mask, unsigned int maskVal)
+{
+    int i = 0;
+    psVector* tmp = NULL;
+
+    if (in->type.type == PS_TYPE_S32) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.S32[i];
+        }
+    } else if (in->type.type == PS_TYPE_U32) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.U32[i];
+        }
+    } else if (in->type.type == PS_TYPE_F64) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.F64[i];
+        }
+    } else if (in->type.type == PS_TYPE_F32) {
+        // do nothing
+    } else {
+        psAbort(__func__, "unsupported vector type 0x%x\n", in->type.type);
+    }
+    return (tmp);
+}
+
+/******************************************************************************
+psVectorStats(myVector, maskVector, maskVal, stats): this is the public API
+function which calls the above private stats functions based on what bits
+were set in stats->options.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    The stats structure.
+ 
+NOTE: The current strategy is to implement everything assuming that all
+input data is of type PS_TYPE_F32.  Once the basic code is in place, we will
+macro-ize everything and add PS_TYPE_U16 and PS_TYPE_F64.
+ *****************************************************************************/
+psStats* psVectorStats(psStats* stats, psVector* in, psVector* mask, unsigned int maskVal)
+{
+    psVector* inF32;
+    int mustFreeTmp = 1;
+
+    // NOTE: Verify that this is the correct action.
+    if (in == NULL) {
+        return (stats);
+    }
+    if (stats == NULL) {
+        return (NULL);
+    }
+
+    inF32 = p_psConvertToF32(stats, in, mask, maskVal);
+    if (inF32 == NULL) {
+        inF32 = in;
+        mustFreeTmp = 0;
+    }
+    // XXX: Should we abort if (stats->min == stats->max)?
+    if ((stats->options & PS_STAT_USE_RANGE) && (stats->min >= stats->max)) {
+        psAbort(__func__, "psVectorStats() called with range: %f to %f\n", stats->min, stats->max);
+    }
+    // PS_CHECK_VECTOR_TYPE(in, PS_TYPE_F32);
+    if (mask != NULL) {
+        PS_CHECK_NULL_VECTOR(mask);
+        PS_CHECK_EMPTY_VECTOR(mask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(mask, in);
+        PS_CHECK_VECTOR_TYPE(mask, PS_TYPE_U8);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_MEAN) {
+        p_psVectorSampleMean(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_MEDIAN) {
+        p_psVectorSampleMedian(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    // NOTE: The Stdev calculation requires the mean.  Should we assume the
+    // mean has already been calculated? Or should we always calculate it?
+    if (stats->options & PS_STAT_SAMPLE_STDEV) {
+        p_psVectorSampleMean(in, mask, maskVal, stats);
+        p_psVectorSampleStdev(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_QUARTILE) {
+        p_psVectorSampleQuartiles(in, mask, maskVal, stats);
+    }
+    // Since the various robust stats quantities share much computation, they
+    // are grouped together in a single private function:
+    // p_psVectorRobustStats()
+    if ((stats->options & PS_STAT_ROBUST_MEAN) ||
+            (stats->options & PS_STAT_ROBUST_MEDIAN) ||
+            (stats->options & PS_STAT_ROBUST_MODE) ||
+            (stats->options & PS_STAT_ROBUST_STDEV) || (stats->options & PS_STAT_ROBUST_QUARTILE)) {
+        p_psVectorRobustStats(in, mask, maskVal, stats);
+    }
+
+    if ((stats->options & PS_STAT_CLIPPED_MEAN) || (stats->options & PS_STAT_CLIPPED_STDEV)) {
+        p_psVectorClippedStats(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_MAX) {
+        p_psVectorMax(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_MIN) {
+        p_psVectorMin(in, mask, maskVal, stats);
+    }
+
+    if (mustFreeTmp == 1) {
+        psFree(inF32);
+    }
+    return (stats);
+}
Index: /tags/rel2_1/psLib/src/dataManip/psStats.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psStats.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psStats.h	(revision 1553)
@@ -0,0 +1,185 @@
+
+/** @file  psStats.h
+ *  \brief basic statistical operations
+ *  @ingroup Stats
+ *
+ *  This file will hold the definition of the histogram and stats data
+ *  structures.  It also contains prototypes for procedures which operate
+ *  on those data structures.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:16:04 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_STATS_H)
+#define PS_STATS_H
+
+#include "psVector.h"
+
+/// @addtogroup Stats
+/// @{
+
+/******************************************************************************
+    Statistical functions and data structures.
+ *****************************************************************************/
+
+/** enumeration of statistical calculation options
+ *
+ *  @see psStats, psVectorStats, psImageStats
+ */
+typedef enum {
+    PS_STAT_SAMPLE_MEAN = 0x000001,
+    PS_STAT_SAMPLE_MEDIAN = 0x000002,
+    PS_STAT_SAMPLE_STDEV = 0x000004,
+    PS_STAT_SAMPLE_QUARTILE = 0x000008,
+    PS_STAT_ROBUST_MEAN = 0x000010,
+    PS_STAT_ROBUST_MEDIAN = 0x000020,
+    PS_STAT_ROBUST_MODE = 0x000040,
+    PS_STAT_ROBUST_STDEV = 0x000080,
+    PS_STAT_ROBUST_QUARTILE = 0x000100,
+    PS_STAT_CLIPPED_MEAN = 0x000200,
+    PS_STAT_CLIPPED_STDEV = 0x000400,
+    PS_STAT_MAX = 0x000800,
+    PS_STAT_MIN = 0x001000,
+    PS_STAT_USE_RANGE = 0x002000,
+    PS_STAT_USE_BINSIZE = 0x004000,
+    PS_STAT_ROBUST_FOR_SAMPLE = 0x008000
+} psStatsOptions;
+
+/** This is the generic statistics structure.  It contails the data members
+    for the various statistic values.  It also contains the options member to
+    specifiy which statistics should be calculated. */
+typedef struct
+{
+    double sampleMean;          ///< formal mean of sample
+    double sampleMedian;        ///< formal median of sample
+    double sampleStdev;         ///< standard deviation of sample
+    double sampleUQ;            ///< upper quartile of sample
+    double sampleLQ;            ///< lower quartile of sample
+    double sampleLimit;         ///<
+    double robustMean;          ///< robust mean of array
+    double robustMedian;        ///< robust median of array
+    double robustMode;          ///< Robust mode of array
+    double robustStdev;         ///< robust standard deviation of array
+    double robustUQ;            ///< robust upper quartile
+    double robustLQ;            ///< robust lower quartile
+    double XXX;
+    double robustN50;           ///<
+    double robustNfit;          ///<
+    double clippedMean;         ///< Nsigma clipped mean
+    double clippedStdev;        ///< standard deviation after clipping
+    double clipSigma;           ///< Nsigma used for clipping; user input
+    int clipIter;               ///< Number of clipping iterations; user input
+    double min;                 ///< minimum data value in array
+    double max;                 ///< maximum data value in array
+    double binsize;             ///<
+    psStatsOptions options;     ///< bitmask of calculated values
+}
+psStats;
+
+/** Performs statistical calculations on a vector.
+ *
+ *  @return psStats*    the statistical results as specified by stats->options
+ */
+psStats* psVectorStats(
+    psStats* stats,
+    ///< stats structure defines stats to be calculated and how
+
+    psVector* in,
+    ///< Vector to be analysed: must be F32
+
+    psVector* mask,
+    ///< Ignore elements where (maskVector & maskVal) != 0: must be INT or NULL
+
+    unsigned int maskVal
+    ///< Only mask elements with one of these bits set in maskVector
+);
+
+/** Allocator of the psStats structure.
+ *
+ *  @return psStats*    A new psStats struct with the options member set to the
+ *                      value given.
+ */
+psStats* psStatsAlloc(
+    psStatsOptions options             ///< Statistics to calculate
+);
+
+/******************************************************************************
+    Histogram functions and data structures.
+ *****************************************************************************/
+
+/** The basic histogram structure which contains bounds and bins.
+ *
+ *  In this structure, the vector bounds specifies the boundaries of the 
+ *  histogram bins, and must of type psF32, while nums specifies the number 
+ *  of entries in the bin, and must of type psU32. The value of bounds.n must 
+ *  therefore be 1 greater than than nums.n. The two values minNum and maxNum 
+ *  are the number of data values which fell below the lower limit bound or 
+ *  above the upper limit bound, respectively.
+ */
+typedef struct
+{
+    psVector* bounds;                  ///< Bounds for the bins (type F32)
+    psVector* nums;                    ///< Number in each of the bins (INT)
+    int minNum;                        ///< Number below the minimum
+    int maxNum;                        ///< Number above the maximum
+    bool uniform;                      ///< Is it a uniform distribution?
+}
+psHistogram;
+
+/** Allocator for psHistogram where the bounds of the bins are implicitly
+ *  specified through simply specifying an upper and lower limit along with 
+ *  the size of the bins. 
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAlloc(
+    float lower,                       ///< Lower limit for the bins
+    float upper,                       ///< Upper limit for the bins
+    int n                              ///< Number of bins
+);
+
+/** Allocator for psHistogram where the bounds of the bins are explicitly
+ *  specified. 
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAllocGeneric(
+    const psVector* restrict bounds    ///< Bounds for the bins
+);
+
+/** Calculate a histogram
+ *
+ *  The following function populates the histogram bins from the specified 
+ *  vector (in). It alters and returns the histogram out structure. The input
+ *  vector may be of types psU8, psU16, psF32, psF64.
+ *
+ *  @return psHistogram*   histogram result
+ */
+psHistogram* psVectorHistogram(
+    psHistogram* out,                  ///< Histogram data
+    const psVector* restrict in,       ///< Vector to analyse
+    const psVector* restrict mask,     ///< Mask dat for input vector
+    unsigned int maskVal               ///< Mask value
+);
+
+/** Extracts the statistic value specified by stats->options.
+ *
+ *  @return bool    If more than one statistic result is set in stats->options,
+ *                  false is returned and the value parameter is not set, 
+ *                  otherwise true is returned.
+ */
+bool p_psGetStatValue(
+    const psStats* stats,
+    ///< the statistic struct to operate on
+
+    double *value
+    ///< if return is true, this is set to the specified statistic value by stats->options
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/dataManip/psVectorFFT.c
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psVectorFFT.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psVectorFFT.c	(revision 1553)
@@ -0,0 +1,741 @@
+
+/** @file  psFFT.c
+*
+*  @brief Contains FFT transforms functions
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 18:54:38 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <complex.h>
+#include <fftw3.h>
+
+#include "psFFT.h"
+#include "psError.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psImageExtraction.h"
+
+#define P_FFTW_PLAN_RIGOR FFTW_ESTIMATE
+
+static bool p_fftwWisdomImported = false;
+
+psImage* psImageFFT(psImage* out, const psImage* in, psFftDirection direction)
+{
+    unsigned int numCols;
+    unsigned int numRows;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_C32 && direction == PS_FFT_REVERSE) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if (type != PS_TYPE_F32 && direction == PS_FFT_FORWARD) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    out = psImageCopy(out, in, PS_TYPE_C32);
+
+    plan = fftwf_plan_dft_2d(numCols, numRows,
+                             (fftwf_complex *) out->data.C32[0],
+                             (fftwf_complex *) out->data.C32[0], direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+
+}
+
+psImage* psImageReal(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just an image copy was performed.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageImaginary(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zero image was returned.");
+        out = psImageRecycle(out, numCols, numRows, type);
+        memset(out->data.V[0], 0, PSELEMTYPE_SIZEOF(type) * numCols * numRows);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageComplex(psImage* out, const psImage* real, const psImage* imag)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    numCols = real->numCols;
+    numRows = real->numRows;
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psImageComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (imag->numCols != numCols || imag->numRows != numRows) {
+        psError(__func__, "The inputs to psImageComplex must be the same dimensions.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psImageComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_F32 && type != PS_TYPE_F64) {
+        psError(__func__, "The input type to psImageComplex must be a floating point.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outRow;
+        psF32* realRow;
+        psF32* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            realRow = real->data.F32[row];
+            imagRow = imag->data.F32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else if (type == PS_TYPE_F64) {
+        psC64* outRow;
+        psF64* realRow;
+        psF64* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            realRow = real->data.F64[row];
+            imagRow = imag->data.F64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageConjugate(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Image copy was performed instead.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]) - I * cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psC64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]) - I * cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImagePowerSpectrum(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+    int numElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+    numElementsSquared = numCols * numCols * numRows * numRows;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+        psF32 real;
+        psF32 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = (real * real + imag * imag) / numElementsSquared;
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+        psF64 real;
+        psF64 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = real * real + imag * imag / numElementsSquared;
+            }
+        }
+    } else {
+        psError(__func__, "Can not power spectrum for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
+
+/************************************** Vector Functions ***************************************/
+
+psVector* psVectorFFT(psVector* out, const psVector* in, psFftDirection direction)
+{
+    unsigned int numElements;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if ((type != PS_TYPE_C32) && (direction == PS_FFT_REVERSE)) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if ((type != PS_TYPE_F32) && (direction == PS_FFT_FORWARD)) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numElements = in->n;
+
+    out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+    out->n = numElements;
+
+    if (type == PS_TYPE_F32) {
+        // need to convert to complex
+        psC32* outVec = out->data.C32;
+        psF32* inVec = in->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    } else {
+        psC32* outVec = out->data.C32;
+        psC32* inVec = in->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    }
+
+    plan = fftwf_plan_dft_1d(numElements,
+                             (fftwf_complex *) out->data.C32,
+                             (fftwf_complex *) out->data.C32, direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+}
+
+psVector* psVectorReal(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just a vector copy was performed.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, numElements * PSELEMTYPE_SIZEOF(type));
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorImaginary(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zeroed vector was returned.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memset(out->data.V, 0, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorComplex(psVector* out, const psVector* real, const psVector* imag)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    if (real->n < imag->n) {
+        numElements = real->n;
+    } else {
+        numElements = imag->n;
+    }
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psVectorComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psVectorComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outVec;
+        psF32* realVec = real->data.F32;
+        psF32* imagVec = imag->data.F32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = realVec[i] + I * imagVec[i];
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorConjugate(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Vector copy was performed instead.");
+
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]) - I * cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorPowerSpectrum(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int outNumElements;
+    unsigned int inNumElements;
+    unsigned int inHalfNumElements;
+    unsigned int inNumElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    inNumElements = in->n;
+    inNumElementsSquared = inNumElements * inNumElements;
+    inHalfNumElements = inNumElements / 2;
+    outNumElements = inHalfNumElements + 1;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+        psF32 inAbs1;
+        psF32 inAbs2;
+
+        out = psVectorRecycle(out, outNumElements, PS_TYPE_F32);
+        out->n = outNumElements;
+        outVec = out->data.F32;
+
+        // from ADD: P_0 = |C_0|^2/N^2
+        inAbs1 = cabsf(inVec[0]);
+        outVec[0] = inAbs1 * inAbs1 / inNumElementsSquared;
+
+        // from ADD: P_j = (|C_j|^2+|C_N-j|^2)/N^2, where j = 1,2,...,(N/2-1)
+        for (unsigned int i = 1; i < inHalfNumElements; i++) {
+            inAbs1 = cabsf(inVec[i]);
+            inAbs2 = cabsf(inVec[inNumElements - i]);
+            outVec[i] = (inAbs1 * inAbs1 + inAbs2 * inAbs2) / inNumElementsSquared;
+        }
+
+        // from ADD: P_N/2 = |C_N/2|^2/N^2
+        inAbs1 = cabsf(inVec[inHalfNumElements]);
+        outVec[inHalfNumElements] = inAbs1 * inAbs1 / inNumElementsSquared;
+    } else {
+        psError(__func__, "Can not power spectrum for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
Index: /tags/rel2_1/psLib/src/dataManip/psVectorFFT.h
===================================================================
--- /tags/rel2_1/psLib/src/dataManip/psVectorFFT.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/dataManip/psVectorFFT.h	(revision 1553)
@@ -0,0 +1,158 @@
+
+/** @file  psFFT.h
+ *
+ *  @brief Contains FFT transforms functions
+ *
+ *  @ingroup Transform
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 18:54:38 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FFT_H
+#define PS_FFT_H
+
+#include "psImage.h"
+#include "psVector.h"
+
+/// @addtogroup Transform
+/// @{
+
+/** Specify direction of FFT */
+typedef enum {
+    /// psImageFFT/psVectorFFT should perform a forward FFT.
+    PS_FFT_FORWARD = (-1),
+
+    /// psImageFFT/psVectorFFT should perform a reverse FFT.
+    PS_FFT_REVERSE = (+1)
+} psFftDirection;
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the image of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input image may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psImage* the FFT transformation result
+ */
+psImage* psImageFFT(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in,                 ///< the psImage to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex image
+ * 
+ *  @return psImage*   real portion of the input image.
+ */
+psImage* psImageReal(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract real portion from
+);
+
+/** extract the imaginary portion of a complex image
+ * 
+ *  @return psImage*   imaginary portion of the input image.
+ */
+psImage* psImageImaginary(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract imaginary portion from
+);
+
+/** creates a complex image from separate real and imaginary plane images
+ * 
+ *  @return psImage*   resulting complex image
+ */
+psImage* psImageComplex(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* real,               ///< the real plane image
+    const psImage* imag                ///< the imaginary plane image
+);
+
+/** computes the complex conjugate of an image
+ * 
+ *  @return psImage*   the complex conjugate of the 'in' image
+ */
+psImage* psImageConjugate(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to compute conjugate of
+);
+
+/** computes the power spectrum of an image
+ * 
+ *  @return psImage*   the power spectrum of the 'in' image
+ */
+psImage* psImagePowerSpectrum(
+    psImage* out,                       ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                   ///< the psImage to power spectrum of
+);
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the vector of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input vector may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psVector* the FFT transformation result
+ */
+psVector* psVectorFFT(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in,                ///< the vector to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex vector
+ * 
+ *  @return psVector*   real portion of the input vector.
+ */
+psVector* psVectorReal(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                ///< the psVector to extract real portion from
+);
+
+/** extract the imaginary portion of a complex vector
+ * 
+ *  @return psVector*   imaginary portion of the input vector.
+ */
+psVector* psVectorImaginary(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to extract imaginary portion from
+);
+
+/** creates a complex vector from separate real and imaginary vectors
+ * 
+ *  @return psVector*   resulting complex vector
+ */
+psVector* psVectorComplex(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* real,              ///< the real vector
+    const psVector* imag               ///< the imaginary vector
+);
+
+/** computes the complex conjugate of a vector
+ * 
+ *  @return psVector*   the complex conjugate of the 'in' vector
+ */
+psVector* psVectorConjugate(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to compute conjugate of
+);
+
+/** computes the power spectrum of a vector
+ * 
+ *  @return psVector*   the power spectrum of the 'in' vector
+ */
+psVector* psVectorPowerSpectrum(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to power spectrum of
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/fft/psVectorFFT.c
===================================================================
--- /tags/rel2_1/psLib/src/fft/psVectorFFT.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/fft/psVectorFFT.c	(revision 1553)
@@ -0,0 +1,741 @@
+
+/** @file  psFFT.c
+*
+*  @brief Contains FFT transforms functions
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 18:54:38 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <complex.h>
+#include <fftw3.h>
+
+#include "psFFT.h"
+#include "psError.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psImageExtraction.h"
+
+#define P_FFTW_PLAN_RIGOR FFTW_ESTIMATE
+
+static bool p_fftwWisdomImported = false;
+
+psImage* psImageFFT(psImage* out, const psImage* in, psFftDirection direction)
+{
+    unsigned int numCols;
+    unsigned int numRows;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_C32 && direction == PS_FFT_REVERSE) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if (type != PS_TYPE_F32 && direction == PS_FFT_FORWARD) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    out = psImageCopy(out, in, PS_TYPE_C32);
+
+    plan = fftwf_plan_dft_2d(numCols, numRows,
+                             (fftwf_complex *) out->data.C32[0],
+                             (fftwf_complex *) out->data.C32[0], direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+
+}
+
+psImage* psImageReal(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just an image copy was performed.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageImaginary(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zero image was returned.");
+        out = psImageRecycle(out, numCols, numRows, type);
+        memset(out->data.V[0], 0, PSELEMTYPE_SIZEOF(type) * numCols * numRows);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageComplex(psImage* out, const psImage* real, const psImage* imag)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    numCols = real->numCols;
+    numRows = real->numRows;
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psImageComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (imag->numCols != numCols || imag->numRows != numRows) {
+        psError(__func__, "The inputs to psImageComplex must be the same dimensions.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psImageComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type != PS_TYPE_F32 && type != PS_TYPE_F64) {
+        psError(__func__, "The input type to psImageComplex must be a floating point.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outRow;
+        psF32* realRow;
+        psF32* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            realRow = real->data.F32[row];
+            imagRow = imag->data.F32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else if (type == PS_TYPE_F64) {
+        psC64* outRow;
+        psF64* realRow;
+        psF64* imagRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            realRow = real->data.F64[row];
+            imagRow = imag->data.F64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = realRow[col] + I * imagRow[col];
+            }
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageConjugate(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Image copy was performed instead.");
+        return psImageCopy(out, in, type);
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outRow;
+        psC32* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = crealf(inRow[col]) - I * cimagf(inRow[col]);
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psC64* outRow;
+        psC64* inRow;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.C64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                outRow[col] = creal(inRow[col]) - I * cimag(inRow[col]);
+            }
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImagePowerSpectrum(psImage* out, const psImage* in)
+{
+    psElemType type;
+    unsigned int numCols;
+    unsigned int numRows;
+    int numElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numCols = in->numCols;
+    numRows = in->numRows;
+    numElementsSquared = numCols * numCols * numRows * numRows;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outRow;
+        psC32* inRow;
+        psF32 real;
+        psF32 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F32[row];
+            inRow = in->data.C32[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = (real * real + imag * imag) / numElementsSquared;
+            }
+        }
+    } else if (type == PS_TYPE_C64) {
+        psF64* outRow;
+        psC64* inRow;
+        psF64 real;
+        psF64 imag;
+
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
+        for (unsigned int row = 0; row < numRows; row++) {
+            outRow = out->data.F64[row];
+            inRow = in->data.C64[row];
+
+            for (unsigned int col = 0; col < numCols; col++) {
+                real = crealf(inRow[col]);
+                imag = cimagf(inRow[col]);
+                outRow[col] = real * real + imag * imag / numElementsSquared;
+            }
+        }
+    } else {
+        psError(__func__, "Can not power spectrum for given image type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
+
+/************************************** Vector Functions ***************************************/
+
+psVector* psVectorFFT(psVector* out, const psVector* in, psFftDirection direction)
+{
+    unsigned int numElements;
+    psElemType type;
+    fftwf_plan plan;
+
+    /* got good image data? */
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+
+    if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
+        psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
+        psFree(out);
+        return NULL;
+    }
+
+    if ((type != PS_TYPE_C32) && (direction == PS_FFT_REVERSE)) {
+        psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+
+    }
+
+    if ((type != PS_TYPE_F32) && (direction == PS_FFT_FORWARD)) {
+        psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    /* make sure the system-level wisdom information is imported. */
+    if (!p_fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        p_fftwWisdomImported = true;
+    }
+
+    numElements = in->n;
+
+    out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+    out->n = numElements;
+
+    if (type == PS_TYPE_F32) {
+        // need to convert to complex
+        psC32* outVec = out->data.C32;
+        psF32* inVec = in->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    } else {
+        psC32* outVec = out->data.C32;
+        psC32* inVec = in->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = inVec[i];
+        }
+    }
+
+    plan = fftwf_plan_dft_1d(numElements,
+                             (fftwf_complex *) out->data.C32,
+                             (fftwf_complex *) out->data.C32, direction, P_FFTW_PLAN_RIGOR);
+
+    /* check if a plan exists now */
+    if (plan == NULL) {
+        psError(__func__, "Failed to create FFTW plan.");
+        psFree(out);
+        return NULL;
+    }
+
+    /* finally, call FFTW with the plan made above */
+    fftwf_execute(plan);
+
+    fftwf_destroy_plan(plan);
+
+    return out;
+}
+
+psVector* psVectorReal(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
+                 "Just a vector copy was performed.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, numElements * PSELEMTYPE_SIZEOF(type));
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract real component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorImaginary(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just zeroed image of same size */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
+                 "A zeroed vector was returned.");
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memset(out->data.V, 0, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_F32);
+        out->n = numElements;
+        outVec = out->data.F32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not extract imaginary component from given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorComplex(psVector* out, const psVector* real, const psVector* imag)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (real == NULL || imag == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = real->type.type;
+    if (real->n < imag->n) {
+        numElements = real->n;
+    } else {
+        numElements = imag->n;
+    }
+
+    if (imag->type.type != type) {
+        psError(__func__, "The inputs to psVectorComplex must be the same type.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "The inputs to psVectorComplex can not be complex.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_F32) {
+        psC32* outVec;
+        psF32* realVec = real->data.F32;
+        psF32* imagVec = imag->data.F32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = realVec[i] + I * imagVec[i];
+        }
+    } else {
+        psError(__func__, "Can not merge real and imaginary portions for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorConjugate(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int numElements;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    numElements = in->n;
+
+    /* if not a complex number, this is logically just a image copy */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        // Warn user, as this is probably not expected
+        psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
+                 "Vector copy was performed instead.");
+
+        out = psVectorRecycle(out, numElements, type);
+        out->n = numElements;
+        memcpy(out->data.V, in->data.V, PSELEMTYPE_SIZEOF(type) * numElements);
+        return out;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psC32* outVec;
+        psC32* inVec = in->data.C32;
+
+        out = psVectorRecycle(out, numElements, PS_TYPE_C32);
+        out->n = numElements;
+        outVec = out->data.C32;
+
+        for (unsigned int i = 0; i < numElements; i++) {
+            outVec[i] = crealf(inVec[i]) - I * cimagf(inVec[i]);
+        }
+    } else {
+        psError(__func__, "Can not compute complex conjugate for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psVector* psVectorPowerSpectrum(psVector* out, const psVector* in)
+{
+    psElemType type;
+    unsigned int outNumElements;
+    unsigned int inNumElements;
+    unsigned int inHalfNumElements;
+    unsigned int inNumElementsSquared;
+
+    if (in == NULL) {
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    inNumElements = in->n;
+    inNumElementsSquared = inNumElements * inNumElements;
+    inHalfNumElements = inNumElements / 2;
+    outNumElements = inHalfNumElements + 1;
+
+    /* if not a complex number, this is not implemented */
+    if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
+        psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (type == PS_TYPE_C32) {
+        psF32* outVec;
+        psC32* inVec = in->data.C32;
+        psF32 inAbs1;
+        psF32 inAbs2;
+
+        out = psVectorRecycle(out, outNumElements, PS_TYPE_F32);
+        out->n = outNumElements;
+        outVec = out->data.F32;
+
+        // from ADD: P_0 = |C_0|^2/N^2
+        inAbs1 = cabsf(inVec[0]);
+        outVec[0] = inAbs1 * inAbs1 / inNumElementsSquared;
+
+        // from ADD: P_j = (|C_j|^2+|C_N-j|^2)/N^2, where j = 1,2,...,(N/2-1)
+        for (unsigned int i = 1; i < inHalfNumElements; i++) {
+            inAbs1 = cabsf(inVec[i]);
+            inAbs2 = cabsf(inVec[inNumElements - i]);
+            outVec[i] = (inAbs1 * inAbs1 + inAbs2 * inAbs2) / inNumElementsSquared;
+        }
+
+        // from ADD: P_N/2 = |C_N/2|^2/N^2
+        inAbs1 = cabsf(inVec[inHalfNumElements]);
+        outVec[inHalfNumElements] = inAbs1 * inAbs1 / inNumElementsSquared;
+    } else {
+        psError(__func__, "Can not power spectrum for given vector type (%d).", type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
Index: /tags/rel2_1/psLib/src/fft/psVectorFFT.h
===================================================================
--- /tags/rel2_1/psLib/src/fft/psVectorFFT.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/fft/psVectorFFT.h	(revision 1553)
@@ -0,0 +1,158 @@
+
+/** @file  psFFT.h
+ *
+ *  @brief Contains FFT transforms functions
+ *
+ *  @ingroup Transform
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 18:54:38 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FFT_H
+#define PS_FFT_H
+
+#include "psImage.h"
+#include "psVector.h"
+
+/// @addtogroup Transform
+/// @{
+
+/** Specify direction of FFT */
+typedef enum {
+    /// psImageFFT/psVectorFFT should perform a forward FFT.
+    PS_FFT_FORWARD = (-1),
+
+    /// psImageFFT/psVectorFFT should perform a reverse FFT.
+    PS_FFT_REVERSE = (+1)
+} psFftDirection;
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the image of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input image may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psImage* the FFT transformation result
+ */
+psImage* psImageFFT(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in,                 ///< the psImage to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex image
+ * 
+ *  @return psImage*   real portion of the input image.
+ */
+psImage* psImageReal(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract real portion from
+);
+
+/** extract the imaginary portion of a complex image
+ * 
+ *  @return psImage*   imaginary portion of the input image.
+ */
+psImage* psImageImaginary(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to extract imaginary portion from
+);
+
+/** creates a complex image from separate real and imaginary plane images
+ * 
+ *  @return psImage*   resulting complex image
+ */
+psImage* psImageComplex(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* real,               ///< the real plane image
+    const psImage* imag                ///< the imaginary plane image
+);
+
+/** computes the complex conjugate of an image
+ * 
+ *  @return psImage*   the complex conjugate of the 'in' image
+ */
+psImage* psImageConjugate(
+    psImage* out,                      ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                  ///< the psImage to compute conjugate of
+);
+
+/** computes the power spectrum of an image
+ * 
+ *  @return psImage*   the power spectrum of the 'in' image
+ */
+psImage* psImagePowerSpectrum(
+    psImage* out,                       ///< a psImage to recycle.  If NULL, a new psImage is made.
+    const psImage* in                   ///< the psImage to power spectrum of
+);
+
+/** Forward and reverse FFT calculations.
+ *
+ *  This takes as input the vector of interest (in) and the direction 
+ *  (direction), which is specified by an enumerated type psFftDirection.
+ *  The input vector may be of type psF32 or psC32, the result is always 
+ *  psC32. If the input vector is psF32, the direction must be forward. 
+ *  
+ *  @return psVector* the FFT transformation result
+ */
+psVector* psVectorFFT(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in,                ///< the vector to apply transform to
+    psFftDirection direction           ///< the direction of the transform
+);
+
+/** extract the real portion of a complex vector
+ * 
+ *  @return psVector*   real portion of the input vector.
+ */
+psVector* psVectorReal(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                ///< the psVector to extract real portion from
+);
+
+/** extract the imaginary portion of a complex vector
+ * 
+ *  @return psVector*   imaginary portion of the input vector.
+ */
+psVector* psVectorImaginary(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to extract imaginary portion from
+);
+
+/** creates a complex vector from separate real and imaginary vectors
+ * 
+ *  @return psVector*   resulting complex vector
+ */
+psVector* psVectorComplex(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* real,              ///< the real vector
+    const psVector* imag               ///< the imaginary vector
+);
+
+/** computes the complex conjugate of a vector
+ * 
+ *  @return psVector*   the complex conjugate of the 'in' vector
+ */
+psVector* psVectorConjugate(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to compute conjugate of
+);
+
+/** computes the power spectrum of a vector
+ * 
+ *  @return psVector*   the power spectrum of the 'in' vector
+ */
+psVector* psVectorPowerSpectrum(
+    psVector* out,                     ///< a psVector to recycle.  If NULL, a new psVector is made.
+    const psVector* in                 ///< the psVector to power spectrum of
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/image/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/image/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/Makefile	(revision 1553)
@@ -0,0 +1,84 @@
+###############################################################################
+##
+##  Makefile:   collections
+##
+##  $Revision: 1.2 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-07-29 21:43:11 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+###############################################################################
+
+# Define variable prefix to the top level project - psLib
+# This is necessary for definition is Makefile.Globals uses prefix
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+# Define the two targets to be built
+
+TARGET_STATIC  = libpslib.a
+
+# Include the make global definitions for the project
+
+include ../Makefile.Globals
+
+# Set CFLAGS used by the implicit rule to compile .c
+
+CFLAGS := $(CFLAGS_RELOC) -I../sysUtils -I../dataManip -I../collections
+
+# Define the source objects
+ 
+SRC_OBJS = psImage.o \
+           psImageExtraction.o \
+           psImageIO.o \
+           psImageManip.o \
+           psImageStats.o
+
+OBJS = $(addprefix makedir/,$(SRC_OBJS))
+
+# Define PHONY target "all" which will make all the necessary items
+
+all: $(TARGET_STATIC)
+
+# Rule to make static library
+
+libpslib.a: $(OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs ../$@ $(OBJS)
+
+# Define PHONY target "install" which will install necessary files
+
+install: $(TARGET_STATIC)
+	install *.h $(includedir)
+
+# Define PHONY target "distclean" which will cleanup the distribution
+
+distclean:	clean
+	$(RM) ../$(TARGET_STATIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+
+clean:
+	@echo "    Deleting intermediate files for 'collections'"
+	$(RM) $(OBJS) *.lint $(SRC_OBJS:.o=.i)
+
+cleandep:
+	$(RM) $(OBJS:.o=.d)
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+%.i: %.c
+	$(CC) -E $(CFLAGS) -o $@ $<
+
+makedir/%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+makedir/%.d: %.c
+	$(CC) -MM $(CFLAGS) $< > $@.tmp
+	sed 's|\($*\)\.o[ :]*|\1.o $@ : |g' $@.tmp > $@
+	$(RM) -f $@.tmp
+
+include $(OBJS:.o=.d)
Index: /tags/rel2_1/psLib/src/image/psImage.c
===================================================================
--- /tags/rel2_1/psLib/src/image/psImage.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImage.c	(revision 1553)
@@ -0,0 +1,436 @@
+
+/** @file  psImage.c
+ *
+ *  @brief Contains basic image definitions and operations.
+ *
+ *  This file defines the basic type for an image struct and functions useful
+ *  in manupulating images.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ *  That is the routine used to generate matrices.
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+
+#include <string.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psAbort.h"
+#include "psError.h"
+#include "psImage.h"
+
+static void imageFree(psImage* image);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psImage* psImageAlloc(unsigned int numCols, unsigned int numRows, const psElemType type)
+{
+    int area = 0;
+    int elementSize = PSELEMTYPE_SIZEOF(type);  // element
+
+    // size in
+    // bytes
+    int rowSize = numCols * elementSize;        // row
+
+    // size
+
+    // in bytes.
+
+    area = numCols * numRows;
+
+    if (area < 1) {
+        psError(__func__,
+                "Invalid value for number of rows or columns " "(numRows=%d, numCols=%d).", numRows, numCols);
+        return NULL;
+    }
+
+    psImage* image = (psImage* ) psAlloc(sizeof(psImage));
+
+    if (image == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    p_psMemSetDeallocator(image, (psFreeFcn) imageFree);
+
+    image->data.V = psAlloc(sizeof(void *) * numRows);
+    if (image->data.V == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    image->data.V[0] = psAlloc(area * elementSize);
+    if (image->data.V[0] == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    for (int i = 1; i < numRows; i++) {
+        image->data.V[i] = (void *)((int8_t *) image->data.V[i - 1] + rowSize);
+    }
+
+    *(int *)&image->col0 = 0;
+    *(int *)&image->row0 = 0;
+    *(unsigned int *)&image->numCols = numCols;
+    *(unsigned int *)&image->numRows = numRows;
+    *(psDimen* ) & image->type.dimen = PS_DIMEN_IMAGE;
+    *(psElemType* ) & image->type.type = type;
+    image->parent = NULL;
+    image->nChildren = 0;
+    image->children = NULL;
+
+    return image;
+}
+
+static void imageFree(psImage* image)
+{
+    if (image == NULL) {
+        return;
+    }
+
+    if (image->type.type == PS_TYPE_PTR) {
+        // 2-D array of pointers -- must
+        // dereference
+        unsigned int oldNumRows = image->numRows;
+        unsigned int oldNumCols = image->numCols;
+        psPTR* rowPtr;
+
+        for (unsigned int row = 0; row < oldNumRows; row++) {
+            rowPtr = image->data.PTR[row];
+            for (unsigned int col = 0; col < oldNumCols; col++) {
+                psMemDecrRefCounter(rowPtr[col]);
+            }
+        }
+    }
+
+    psImageFreeChildren(image);
+
+    psFree(image->data.V[0]);
+    psFree(image->data.V);
+    image->data.V = NULL;
+}
+
+psImage* psImageRecycle(psImage* old, unsigned int numCols, unsigned int numRows, const psElemType type)
+{
+    int elementSize = PSELEMTYPE_SIZEOF(type);  // element
+
+    // size in
+    // bytes
+    int rowSize = numCols * elementSize;        // row
+
+    // size
+
+    // in bytes.
+
+    if (old == NULL) {
+        old = psImageAlloc(numCols, numRows, type);
+        return old;
+    }
+
+    if (old->type.dimen != PS_DIMEN_IMAGE) {
+        psError(__func__, "Can not realloc image because input is not an image.");
+        return NULL;
+    }
+
+    if (old->type.type == PS_TYPE_PTR) {
+        // 2-D array of pointers -- must
+        // dereference
+        unsigned int oldNumRows = old->numRows;
+        unsigned int oldNumCols = old->numCols;
+        psPTR* rowPtr;
+
+        for (unsigned int row = 0; row < oldNumRows; row++) {
+            rowPtr = old->data.PTR[row];
+            for (unsigned int col = 0; col < oldNumCols; col++) {
+                psMemDecrRefCounter(rowPtr[col]);
+                rowPtr[col] = NULL;
+            }
+        }
+    }
+
+    /* image already the right size/type? */
+    if (numCols == old->numCols && numRows == old->numRows && type == old->type.type) {
+        return old;
+    }
+    // Resize the image buffer
+    old->data.V[0] = psRealloc(old->data.V[0], numCols * numRows * elementSize);
+    old->data.V = (void **)psRealloc(old->data.V, numRows * sizeof(void *));
+
+    // recreate the row pointers
+    for (int i = 1; i < numRows; i++) {
+        old->data.V[i] = (void *)((int8_t *) old->data.V[i - 1] + rowSize);
+    }
+
+    *(unsigned int *)&old->numCols = numCols;
+    *(unsigned int *)&old->numRows = numRows;
+    *(psElemType* ) & old->type.type = type;
+
+    return old;
+}
+
+int psImageFreeChildren(psImage* image)
+{
+    int i = 0;
+    int nChildren = 0;
+    psImage* *children = NULL;
+    int numFreed = 0;
+
+    if (image == NULL) {
+        return numFreed;
+    }
+
+    nChildren = image->nChildren;
+    children = image->children;
+
+    for (i = 0; i < nChildren; i++) {
+        if (children[i] != NULL) {
+            numFreed++;
+            psFree(children[i]);
+        }
+    }
+    psFree(children);
+
+    image->nChildren = 0;
+    image->children = NULL;
+
+    return numFreed;
+}
+
+/*****************************************************************************
+p_psImagePixelInterpolation(image, x, y): this routine takes as input an
+image and coordinates (x, y) and produces as output the corresponding pixel
+value at the those coordinates.  For fractional corrdinates (x, y), 2-D
+linear interpolation is performed on the image.
+ *****************************************************************************/
+psF32 psImagePixelInterpolate(const psImage* input,
+                              float x, float y, psF32 unexposedValue, psImageInterpolateMode mode)
+{
+
+    if (input == NULL) {
+        psError(__func__, "Image can not be NULL.");
+        return unexposedValue;
+    }
+    #define PSIMAGE_PIXEL_INTERPOLATE_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    switch (mode) { \
+    case PS_INTERPOLATE_FLAT: \
+        return p_psImagePixelInterpolateFLAT_##TYPE(input,x,y,unexposedValue); \
+        break; \
+    case PS_INTERPOLATE_BILINEAR: \
+        return p_psImagePixelInterpolateBILINEAR_##TYPE(input,x,y,unexposedValue); \
+        break; \
+    default: \
+        psError(__func__,"Unsupported interpolation mode (#%d)",mode); \
+    } \
+    break
+
+    switch (input->type.type) {
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U8);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U16);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S8);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S16);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(F32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(F64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(C32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(C64);
+    default:
+        psError(__func__, "Unsupported image datatype (%d)", input->type.type);
+    }
+
+    return unexposedValue;
+}
+
+#define PSIMAGE_PIXEL_INTERPOLATE_FLAT(TYPE) \
+inline psF64 p_psImagePixelInterpolateFLAT_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue) \
+{ \
+    int intX = (int) round((psF64)(x) - 0.5); \
+    int intY = (int) round((psF64)(y) - 0.5); \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    \
+    if ((intX < 0) || \
+            (intX > lastX) || \
+            (intY < 0) || \
+            (intY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    return input->data.TYPE[intY][intX]; \
+}
+
+#define PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(TYPE) \
+inline psC64 p_psImagePixelInterpolateFLAT_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue) \
+{ \
+    int intX = (int) round((psF64)(x) - 0.5); \
+    int intY = (int) round((psF64)(y) - 0.5); \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    \
+    if ((intX < 0) || \
+            (intX > lastX) || \
+            (intY < 0) || \
+            (intY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    return input->data.TYPE[intY][intX]; \
+}
+
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U8)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U16)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S8)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S16)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(F32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(F64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(C32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(C64)
+#define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(TYPE) \
+inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue) \
+{ \
+    double floorX = floor((psF64)(x) - 0.5); \
+    double floorY = floor((psF64)(y) - 0.5); \
+    double fracX = x - 0.5 - floorX; \
+    double fracY = y - 0.5 - floorY; \
+    int intFloorX = (int) floorX; \
+    int intFloorY = (int) floorY; \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    double rx = 0.0; \
+    psF64 pixel = 0.0; \
+    ps##TYPE* currentRow; \
+    ps##TYPE* nextRow; \
+    \
+    if ((intFloorX < 0) || \
+            (intFloorX > lastX) || \
+            (intFloorY < 0) || \
+            (intFloorY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    currentRow = input->data.TYPE[intFloorY]; \
+    if (intFloorY == lastY) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorX < lastX) { \
+            pixel+= fracY * ((psF64)currentRow[intFloorX+1] - \
+                             (psF64)currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    nextRow = input->data.TYPE[intFloorY+1]; \
+    if (intFloorX == lastX) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorY < lastY) { \
+            pixel+= fracX * ((psF64)nextRow[intFloorX] - \
+                             (psF64)currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    \
+    rx = currentRow[intFloorX] + \
+         fracX * ((psF64)currentRow[intFloorX+1] - \
+                  (psF64)currentRow[intFloorX]); \
+    \
+    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
+                          fracX * ((psF64)nextRow[intFloorX+1] - \
+                                   (psF64)nextRow[intFloorX]) - rx); \
+    \
+    return(pixel); \
+}
+#define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(TYPE) \
+inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue) \
+{ \
+    double floorX = floor((psF64)(x) - 0.5); \
+    double floorY = floor((psF64)(y) - 0.5); \
+    double fracX = x - 0.5 - floorX; \
+    double fracY = y - 0.5 - floorY; \
+    int intFloorX = (int) floorX; \
+    int intFloorY = (int) floorY; \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    double rx = 0.0; \
+    psC64 pixel = 0.0; \
+    ps##TYPE* currentRow; \
+    ps##TYPE* nextRow; \
+    \
+    if ((intFloorX < 0) || \
+            (intFloorX > lastX) || \
+            (intFloorY < 0) || \
+            (intFloorY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    currentRow = input->data.TYPE[intFloorY]; \
+    if (intFloorY == lastY) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorX < lastX) { \
+            pixel+= fracY * (currentRow[intFloorX+1] - \
+                             currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    nextRow = input->data.TYPE[intFloorY+1]; \
+    if (intFloorX == lastX) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorY < lastY) { \
+            pixel+= fracX * (nextRow[intFloorX] - \
+                             currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    \
+    rx = currentRow[intFloorX] + \
+         fracX * (currentRow[intFloorX+1] - \
+                  currentRow[intFloorX]); \
+    \
+    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
+                          fracX * (nextRow[intFloorX+1] - \
+                                   nextRow[intFloorX]) - rx); \
+    \
+    return(pixel); \
+}
+
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U8)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U16)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S8)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S16)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(F32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(F64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(C32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(C64)
Index: /tags/rel2_1/psLib/src/image/psImage.h
===================================================================
--- /tags/rel2_1/psLib/src/image/psImage.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImage.h	(revision 1553)
@@ -0,0 +1,162 @@
+
+/** @file  psImage.h
+ *
+ *  @brief Contains basic image definitions and operations
+ *
+ *  This file defines the basic type for an image struct and functions useful
+ *  in manupulating images.
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:05:53 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGE_H
+#define PS_IMAGE_H
+
+#include <complex.h>
+
+#include "psType.h"
+
+/// @addtogroup Image
+/// @{
+
+/** enumeration of options in interpolation
+ *
+ */
+typedef enum {
+    PS_INTERPOLATE_FLAT,               ///< 'flat' interpolation (nearest pixel)
+    PS_INTERPOLATE_BILINEAR            ///< bi-linear interpolation
+} psImageInterpolateMode;
+
+/** Basic image data structure.
+ *
+ * Struct for maintaining image data of varying types. It also contains
+ * information about image size, parent images and children images.
+ *
+ */
+typedef struct psImage
+{
+    const psType type;                 ///< Image data type and dimension.
+    const unsigned int numCols;        ///< Number of columns in image
+    const unsigned int numRows;        ///< Number of rows in image.
+    const int col0;                    ///< Column position relative to parent.
+    const int row0;                    ///< Row position relative to parent.
+
+    union {
+        psU8* *U8;                     ///< Unsigned 8-bit integer data.
+        psU16* *U16;                   ///< Unsigned 16-bit integer data.
+        psU32* *U32;                   ///< Unsigned 32-bit integer data.
+        psU64* *U64;                   ///< Unsigned 64-bit integer data.
+        psS8* *S8;                     ///< Signed 8-bit integer data.
+        psS16* *S16;                   ///< Signed 16-bit integer data.
+        psS32* *S32;                   ///< Signed 32-bit integer data.
+        psS64* *S64;                   ///< Signed 64-bit integer data.
+        psF32* *F32;                   ///< Single-precision float data.
+        psF64* *F64;                   ///< Double-precision float data.
+        psC32* *C32;                   ///< Single-precision complex data.
+        psC64* *C64;                   ///< Double-precision complex data.
+        psPTR* *PTR;                   ///< Void pointers.
+        psPTR* V;                      ///< Pointer to data.
+    } data;                            ///< Union for data types.
+    const struct psImage* parent;      ///< Parent, if a subimage.
+    int nChildren;                     ///< Number of subimages.
+    struct psImage* *children;         ///< Children of this region.
+}
+psImage;
+
+/** Create an image of the specified size and type.
+ *
+ * Uses psLib memory allocation functions to create an image struct of the
+ * specified size and type.
+ *
+ * @return psImage* : Pointer to psImage.
+ *
+ */
+psImage* psImageAlloc(
+    unsigned int numCols,              ///< Number of rows in image.
+    unsigned int numRows,              ///< Number of columns in image.
+    const psElemType type              ///< Type of data for image.
+);
+
+/** Resize a given image to the given size/type.
+ *
+ *  @return psImage* Resized psImage.
+ *
+ */
+psImage* psImageRecycle(
+    psImage* old,                      ///< the psImage to recycle by resizing image buffer
+    unsigned int numCols,              ///< the desired number of columns in image
+    unsigned int numRows,              ///< the desired number of rows in image
+    const psElemType type              ///< the desired datatype of the image
+);
+
+/** Frees all children of a psImage.
+ *
+ *  @return int      Number of children freed.
+ *
+ */
+int psImageFreeChildren(
+    psImage* image                     ///< psImage in which all children shall be deallocated
+);
+
+/** Interpolate image pixel value given floating point coordinates.
+ *
+ *  @return psF32    Pixel value interpolated from image or unexposedValue if
+ *                   given x,y doesn't coorespond to a valid image location
+ */
+psF32 psImagePixelInterpolate(
+    const psImage* input,              ///< input image for interpolation
+    float x,                           ///< column location to derive value of
+    float y,                           ///< row location ot derive value of
+    psF32 unexposedValue,              ///< return value if x,y location is not in image.
+    psImageInterpolateMode mode        ///< interpolation mode
+);
+
+#define p_psImagePixelInterpolateFcns(TYPE) \
+inline psF64 p_psImagePixelInterpolateFLAT_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue \
+                                                 ); \
+inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue \
+                                                     );
+
+#define p_psImagePixelInterpolateComplexFcns(TYPE) \
+inline psC64 p_psImagePixelInterpolateFLAT_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue \
+                                                 ); \
+inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue \
+                                                     );
+
+p_psImagePixelInterpolateFcns(U8)
+p_psImagePixelInterpolateFcns(U16)
+p_psImagePixelInterpolateFcns(U32)
+p_psImagePixelInterpolateFcns(U64)
+p_psImagePixelInterpolateFcns(S8)
+p_psImagePixelInterpolateFcns(S16)
+p_psImagePixelInterpolateFcns(S32)
+p_psImagePixelInterpolateFcns(S64)
+p_psImagePixelInterpolateFcns(F32)
+p_psImagePixelInterpolateFcns(F64)
+p_psImagePixelInterpolateComplexFcns(C32)
+p_psImagePixelInterpolateComplexFcns(C64)
+/// @}
+#endif
Index: /tags/rel2_1/psLib/src/image/psImageExtraction.c
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageExtraction.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageExtraction.c	(revision 1553)
@@ -0,0 +1,491 @@
+
+/** @file  psImageExtraction.c
+*
+*  @brief Contains basic image extraction operations, as specified in the 
+*         PSLIB SDRS sections "Image Pixel Extractions" and "Image Structure
+*         Manipulation".
+*
+*  @ingroup Image
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+
+#include "psMemory.h"
+#include "psImageExtraction.h"
+#include "psError.h"
+
+psImage* psImageSubset(psImage* out,
+                       psImage* image,
+                       unsigned int numCols, unsigned int numRows, unsigned int col0, unsigned int row0)
+{
+    unsigned int elementSize;   // size of image
+
+    // element in
+    // bytes
+    unsigned int outputRowSize; // output row
+
+    // size in bytes
+    unsigned int inputColOffset;        // offset
+
+    // in
+    // bytes
+    // to
+    // first
+    // subset
+
+    // pixel in input row
+
+    if (image == NULL || image->data.V == NULL) {
+        psError(__func__, "Can not subset image because input image or its pixel buffer is NULL.");
+        return NULL;
+    }
+
+    if (image->type.dimen != PS_DIMEN_IMAGE) {
+        psError(__func__, "Can not subset image because input image is not an image.");
+        return NULL;
+    }
+
+    if (numCols < 1 || numRows < 1) {
+        psError(__func__,
+                "Can not subset image because number of rows or columns are zero (%dx%d).", numCols, numRows);
+        return NULL;
+    }
+
+    if (col0 >= image->numCols || row0 >= image->numRows) {
+        psError(__func__,
+                "Can not subset image because col0,row0 (%d,%d) is not a valid pixel location.", col0, row0);
+        return NULL;
+    }
+
+    /* validate subimage size */
+    if (col0 + numCols >= image->numCols || row0 + numRows >= image->numRows) {
+        psError(__func__,
+                "Can not subset image outside of image boundaries (size=%dx%d, "
+                "subset=[%d:%d,%d:%d]).",
+                image->numCols, image->numRows, col0, col0 + numCols, row0, row0 + numRows);
+        return NULL;
+    }
+
+    elementSize = PSELEMTYPE_SIZEOF(image->type.type);
+
+    out = psImageRecycle(out, numCols, numRows, image->type.type);
+
+    // set the parent information into the child
+    // output image
+    *(int *)&out->row0 = row0;
+    *(int *)&out->col0 = col0;
+    *(psImage* *) & out->parent = (psImage* ) image;
+
+    // add output image as a child of the input
+    // image.
+    image->nChildren++;
+    image->children = (psImage* *) psRealloc(image->children, image->nChildren * sizeof(psImage* ));
+    image->children[image->nChildren - 1] = out;
+
+    inputColOffset = elementSize * col0;
+    outputRowSize = elementSize * numCols;
+
+    for (int row = 0; row < numRows; row++) {
+        memcpy(out->data.V[row], image->data.U8[row0 + row] + inputColOffset, outputRowSize);
+    }
+
+    return (out);
+}
+
+psImage* psImageCopy(psImage* restrict output, const psImage* input, psElemType type)
+{
+    psElemType inDatatype;
+    int elementSize;
+    int elements;
+    int numRows;
+    int numCols;
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(__func__, "Can not copy image because input image or its pixel buffer is NULL.");
+        psFree(output);
+        return NULL;
+    }
+
+    if (input == output) {
+        psError(__func__,
+                "Can not copy image because given input and output "
+                "parameter reference the same psImage struct.");
+        psFree(output);
+        return NULL;
+    }
+
+    if (input->type.dimen != PS_DIMEN_IMAGE) {
+        psError(__func__, "Can not copy image because input image is not actually an image.");
+        psFree(output);
+        return NULL;
+    }
+
+    inDatatype = input->type.type;
+    numRows = input->numRows;
+    numCols = input->numCols;
+    elements = numRows * numCols;
+    elementSize = PSELEMTYPE_SIZEOF(inDatatype);
+
+    if (inDatatype == PS_TYPE_PTR || type == PS_TYPE_PTR) {
+        psError(__func__, "Can not copy image to/from a void* matrix");
+        psFree(output);
+        return NULL;
+    }
+
+    output = psImageRecycle(output, numCols, numRows, type);
+
+    // cover the trival case of copy of the same
+    // datatype.
+    if (type == inDatatype) {
+        memcpy(output->data.V[0], input->data.V[0], elementSize * elements);
+        return output;
+    }
+    #define PSIMAGE_ELEMENT_COPY(IN,INTYPE,OUT,OUTTYPE,ELEMENTS) { \
+        ps##INTYPE *in = IN->data.INTYPE[0]; \
+        ps##OUTTYPE *out = OUT->data.OUTTYPE[0]; \
+        for (int e=0;e<ELEMENTS;e++) { \
+            *(out++) = *(in++); \
+        } \
+    }
+
+    #define PSIMAGE_COPY_CASE(OUT,OUTTYPE) \
+    switch (inDatatype) { \
+    case PS_TYPE_S8: \
+        PSIMAGE_ELEMENT_COPY(input,S8,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_S16: \
+        PSIMAGE_ELEMENT_COPY(input,S16,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_S32: \
+        PSIMAGE_ELEMENT_COPY(input,S32,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_S64: \
+        PSIMAGE_ELEMENT_COPY(input,S64,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_U8: \
+        PSIMAGE_ELEMENT_COPY(input,U8,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_U16: \
+        PSIMAGE_ELEMENT_COPY(input,U16,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_U32: \
+        PSIMAGE_ELEMENT_COPY(input,U32,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_U64: \
+        PSIMAGE_ELEMENT_COPY(input,U64,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_F32: \
+        PSIMAGE_ELEMENT_COPY(input,F32,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_F64: \
+        PSIMAGE_ELEMENT_COPY(input,F64,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_C32: \
+        PSIMAGE_ELEMENT_COPY(input,C32,OUT,OUTTYPE,elements); \
+        break; \
+    case PS_TYPE_C64: \
+        PSIMAGE_ELEMENT_COPY(input,C64,OUT,OUTTYPE,elements); \
+        break; \
+    default: \
+        break; \
+    }
+
+    switch (type) {
+    case PS_TYPE_S8:
+        PSIMAGE_COPY_CASE(output, S8);
+        break;
+    case PS_TYPE_S16:
+        PSIMAGE_COPY_CASE(output, S16);
+        break;
+    case PS_TYPE_S32:
+        PSIMAGE_COPY_CASE(output, S32);
+        break;
+    case PS_TYPE_S64:
+        PSIMAGE_COPY_CASE(output, S64);
+        break;
+    case PS_TYPE_U8:
+        PSIMAGE_COPY_CASE(output, U8);
+        break;
+    case PS_TYPE_U16:
+        PSIMAGE_COPY_CASE(output, U16);
+        break;
+    case PS_TYPE_U32:
+        PSIMAGE_COPY_CASE(output, U32);
+        break;
+    case PS_TYPE_U64:
+        PSIMAGE_COPY_CASE(output, U64);
+        break;
+    case PS_TYPE_F32:
+        PSIMAGE_COPY_CASE(output, F32);
+        break;
+    case PS_TYPE_F64:
+        PSIMAGE_COPY_CASE(output, F64);
+        break;
+    case PS_TYPE_C32:
+        PSIMAGE_COPY_CASE(output, C32);
+        break;
+    case PS_TYPE_C64:
+        PSIMAGE_COPY_CASE(output, C64);
+        break;
+    default:
+        break;
+    }
+    return output;
+}
+
+psVector* psImageSlice(psVector* out,
+                       psVector* slicePositions,
+                       const psImage* restrict in,
+                       const psImage* restrict mask,
+                       unsigned int maskVal,
+                       unsigned int col,
+                       unsigned int row,
+                       unsigned int numCols,
+                       unsigned int numRows, psImageCutDirection direction, const psStats* stats)
+{
+    double statVal;
+    psStats* myStats;
+    psElemType type;
+    int inRows;
+    int inCols;
+    int delta = 1;
+    psF64* outData;
+
+    if (in == NULL || in->data.V == NULL) {
+        psError(__func__, "Input image can not be NULL.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (numRows == 0 || numCols == 0) {
+        psError(__func__, "The specified region contains no data (%dx%d)", numCols, numRows);
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    inRows = in->numRows;
+    inCols = in->numCols;
+
+    if (direction == PS_CUT_X_NEG || direction == PS_CUT_Y_NEG) {
+        delta = -1;
+    }
+    // if numRows/numCols is negative, invert the
+    // problem to give positive
+    // numRows/numCols (and cut in opposite
+    // direction).
+    if (numRows < 0) {
+        numRows = -numRows;
+        row -= (numRows - 1);
+        delta = -delta;
+    }
+
+    if (numCols < 0) {
+        numCols = -numCols;
+        col -= (numCols - 1);
+        delta = -delta;
+    }
+
+    if (mask != NULL) {
+        if (inRows != mask->numRows || inCols != mask->numCols) {
+            psError(__func__,
+                    "The mask and image dimensions did not match (%dx%d vs %dx%d)",
+                    mask->numCols, mask->numRows, in->numCols, in->numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__, "The mask datatype (%d) must be %s.", mask->type.type, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    if (row >= inRows || col >= inCols || col + numCols > in->numCols || row + numRows > in->numRows) {
+        psError(__func__,
+                "The specified image region (%d,%d to %d,%d) is outside of image area (0,0 to %d,%d).",
+                col, row, col + numCols - 1, row + numRows - 1, in->numCols - 1, in->numRows - 1);
+        psFree(out);
+        return NULL;
+    }
+    // verify that the stats struct specifies a
+    // single stats operation
+    if (stats == NULL || p_psGetStatValue(stats, &statVal) == false) {
+        psError(__func__, "The stat options didn't specify a single supported statistic type.");
+        psFree(out);
+        return NULL;
+    }
+    // since stats input is const, I need to
+    // create a 'scratch' stats struct
+    myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    if (direction == PS_CUT_X_POS || direction == PS_CUT_X_NEG) {
+        psVector* imgVec = psVectorAlloc(numRows, type);
+        psVector* maskVec = NULL;
+        psMaskType* maskData = NULL;
+        psU32* outPosition = NULL;
+
+        // recycle output to make a proper
+        // sized/type output structure
+        // n.b. type is double as that is the
+        // type given for all stats in
+        // psStats.
+        out = psVectorRecycle(out, numCols, PS_TYPE_F64);
+        if (slicePositions != NULL) {
+            slicePositions = psVectorRecycle(slicePositions, numCols, PS_TYPE_U32);
+            outPosition = slicePositions->data.U32;
+        }
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numCols - 1;
+            if (outPosition != NULL) {
+                outPosition += numCols - 1;
+            }
+        }
+
+        if (mask != NULL) {
+            maskVec = psVectorAlloc(numRows, mask->type.type);
+        }
+        #define PSIMAGE_CUT_VERTICAL(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            psMaskType* maskVecData = NULL; \
+            for (int c=0;c<numCols;c++) { \
+                ps##TYPE *imgData = in->data.TYPE[row] + col + c; \
+                ps##TYPE *imgVecData = imgVec->data.TYPE; \
+                if (maskVec != NULL) { \
+                    maskVecData = maskVec->data.V; \
+                    maskData = (psMaskType* )(mask->data.V[row]) + col + c; \
+                } \
+                for (int r=0;r<numRows;r++) { \
+                    *(imgVecData++) = *imgData; \
+                    imgData += inCols; \
+                    if (maskVecData != NULL) { \
+                        *(maskVecData++) = *maskData; \
+                        maskData += inCols; \
+                    } \
+                } \
+                myStats = psVectorStats(myStats,imgVec,maskVec,maskVal); \
+                (void)p_psGetStatValue(myStats,&statVal); \
+                *outData = statVal; \
+                if (outPosition != NULL) { \
+                    *outPosition = col+c; \
+                    outPosition += delta; \
+                } \
+                outData += delta; \
+            } \
+            break; \
+        }
+
+        switch (type) {
+            PSIMAGE_CUT_VERTICAL(U8);
+            PSIMAGE_CUT_VERTICAL(U16);
+            PSIMAGE_CUT_VERTICAL(U32);
+            PSIMAGE_CUT_VERTICAL(U64);
+            PSIMAGE_CUT_VERTICAL(S8);
+            PSIMAGE_CUT_VERTICAL(S16);
+            PSIMAGE_CUT_VERTICAL(S32);
+            PSIMAGE_CUT_VERTICAL(S64);
+            PSIMAGE_CUT_VERTICAL(F32);
+            PSIMAGE_CUT_VERTICAL(F64);
+            PSIMAGE_CUT_VERTICAL(C32);
+            PSIMAGE_CUT_VERTICAL(C64);
+        default:
+            psError(__func__, "Unsupported datatype (%d)", type);
+            psFree(out);
+            out = NULL;
+        }
+        psFree(imgVec);
+        psFree(maskVec);
+    } else if (direction == PS_CUT_Y_POS || direction == PS_CUT_Y_NEG) {        // Cut
+        //
+        //
+        //
+        //
+        //
+        //
+        //
+        //
+        //
+        // in
+        // Y
+        // direction
+        psVector* imgVec = NULL;
+        psVector* maskVec = NULL;
+        int elementSize = PSELEMTYPE_SIZEOF(type);
+        psU32* outPosition = NULL;
+
+        // fill in psVectors to fake out the
+        // statistics functions.
+        imgVec = psAlloc(sizeof(psVector));
+        imgVec->type = in->type;
+        imgVec->n = imgVec->nalloc = numCols;
+        if (mask != NULL) {
+            maskVec = psAlloc(sizeof(psVector));
+            maskVec->type = mask->type;
+            maskVec->n = maskVec->nalloc = numCols;
+        }
+        // recycle output to make a proper
+        // sized/type output structure
+        // n.b. type is double as that is the
+        // type given for all stats in
+        // psStats.
+        out = psVectorRecycle(out, numRows, PS_TYPE_F64);
+        if (slicePositions != NULL) {
+            slicePositions = psVectorRecycle(slicePositions, numRows, PS_TYPE_U32);
+            outPosition = slicePositions->data.U32;
+        }
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numRows - 1;
+            if (outPosition != NULL) {
+                outPosition += numRows - 1;
+            }
+        }
+
+        for (int r = 0; r < numRows; r++) {
+            // point the vector struct to the
+            // data to calculate the stats
+            imgVec->data.V = (void *)(in->data.U8[row + r] + col * elementSize);
+            if (maskVec != NULL) {
+                maskVec->data.V = (void *)(mask->data.U8[row + r] + col * sizeof(psMaskType));
+            }
+            myStats = psVectorStats(myStats, imgVec, maskVec, maskVal);
+            (void)p_psGetStatValue(myStats, &statVal);  // we
+            // know
+            // it
+            // works
+            // cause we tested it
+            // above
+            *outData = statVal;
+            if (outPosition != NULL) {
+                *outPosition = row + r;
+                outPosition += delta;
+
+            }
+            outData += delta;
+        }
+        psFree(imgVec);
+        psFree(maskVec);
+    } else {                               // don't
+        // know
+        // what
+        // the
+        // direction
+        // flag
+        // is
+        psError(__func__, "Invalid direction flag (%d)", direction);
+        psFree(out);
+        out = NULL;
+    }
+
+    psFree(myStats);
+
+    return out;
+}
Index: /tags/rel2_1/psLib/src/image/psImageExtraction.h
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageExtraction.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageExtraction.h	(revision 1553)
@@ -0,0 +1,152 @@
+
+/** @file  psImageExtraction.h
+*
+*  @brief Contains basic image extraction operations, as specified in the 
+*         PSLIB SDRS sections "Image Pixel Extractions" and "Image Structure
+*         Manipulation".
+*
+*  @ingroup Image
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:40:55 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PSIMAGEEXTRACTION_H
+#define PSIMAGEEXTRACTION_H
+
+#include "psImage.h"
+#include "psVector.h"
+#include "psStats.h"
+
+/// @addtogroup Image
+/// @{
+
+/* Cut direction flag.  Used with psImageCut function.
+ */
+typedef enum {
+    PS_CUT_X_POS,                      ///< Cut in the x dimension from left to right
+    PS_CUT_X_NEG,                      ///< Cut in the x dimension from rigth to left
+    PS_CUT_Y_POS,                      ///< Cut in the y dimension from bottom up
+    PS_CUT_Y_NEG,                      ///< Cut in the y dimension from top down.
+} psImageCutDirection;
+
+/** Create a subimage of the specified area.
+ *
+ * Uses psLib memory allocation functions to create an image based on a larger
+ * one.
+ *
+ * @return psImage* : Pointer to psImage.
+ *
+ */
+psImage* psImageSubset(
+    psImage* out,                      ///< image to recycle, or NULL.
+    psImage* image,                    ///< Parent image.
+    unsigned int numCols,              ///< Subimage width (<= image.nCols - col0).
+    unsigned int numRows,              ///< Subimage height (<= image.nRows - row0).
+    unsigned int col0,                 ///< Subimage col-offset (0 <= col0 < nCol).
+    unsigned int row0                  ///< Subimage row-offset (0 <= row0 < nCol).
+);
+
+/** Makes a copy of a psImage
+ *
+ * @return psImage* Copy of the input psImage.  This may not be equal to the
+ * output parameter
+ *
+ */
+psImage* psImageCopy(
+    psImage* restrict output,          ///< if not NULL, a psImage that could be recycled.
+    const psImage* input,              ///< the psImage to copy
+    psElemType type                    ///< the desired datatype of the returned copy
+);
+
+
+/** Extract pixels from rectlinear region to a vector (array of floats).
+ *
+ *  The output vector contains either nx or ny elements, based on the value of 
+ *  the direction: e.g., if direction is PS_CUT_X_POS, there are nx elements.
+ *  The input region is collapsed in the perpendicular direction, and each 
+ *  element of the output vectors is derived from the statistics of the pixels
+ *  at that direction coordinate. The statistic used to derive the output 
+ *  vector value is specified by stats. Only one of the statistics choices may 
+ *  be specified, otherwise the function must return an error. This function 
+ *  must be defined for the following types: psS8, psU16, psF32, psF64.
+ *
+ * @return psVector    the resulting vector
+ */
+psVector* psImageSlice(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    psVector* slicePositions,
+    ///< If not NULL, it is populated with the coordinate in the slice dimension
+    ///< coorsponding to the output vector's value of the same position in the
+    ///< vector.  This vector maybe resized and retyped as appropriate.
+    const psImage* restrict input,     ///< the input image in which to perform the slice
+    const psImage* restrict mask,      ///< the mask for the input image.
+    unsigned int maskVal,              ///< the mask value to apply to the mask
+    unsigned int col,                  ///< the leftmost column of the slice region
+    unsigned int row,                  ///< the bottommost row of the slice region
+    unsigned int numCols,              ///< the number of columns in the slice region
+    unsigned int numRows,              ///< the number of rows in the slice region
+    psImageCutDirection direction,     ///< the slice dimension and direction
+    const psStats* stats               ///< the statistic to perform in slice operation
+);
+
+/** Extract pixels from an image along a line to a vector (array of floats).
+ *
+ *  The vector (xs,ys) - (xe,ye) forms the basis of the output vector. Pixels 
+ *  are considered in a rectangular region of width dw about this vector. The 
+ *  input region is collapsed in the perpendicular direction, and each element 
+ *  of the output vector represents pixel-sized boxes, where the value is 
+ *  derived from the statistics of the pixels interpolated along the 
+ *  perpendicular direction. The specific algorithm which must be used is 
+ *  described in the PSLib ADD (PSDC-430-006). The statistic used to derive 
+ *  the output vector value is specified by stats. Only one of the statistics 
+ *  choices may be specified, otherwise the function must return an error. 
+ *  This function must be defined for the following types: psS8, psU16, psF32, 
+ *  psF64.
+ *
+ *  @return psVector    resulting vector
+ */
+psVector* psImageCut(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    const psImage* input,              ///< the input image in which to perform the cut
+    const psImage* restrict mask,      ///< the mask for the input image.
+    unsigned int maskVal,              ///< the mask value to apply to the mask
+    float startCol,                    ///< the column of the start of the cut line
+    float startRow,                    ///< the row of the start of the cut line
+    float endCol,                      ///< the column of the end of the cut line
+    float endRow,                      ///< the row of the end of the cut line
+    float width,                       ///< the distance about the line to perform the statistics
+    const psStats* stats               ///< the statistic to perform in operation
+);
+
+/** Extract radial region data to a vector. A vector is constructed where each
+ *  vector elements is derived from the statistics of the pixels which land 
+ *  within one of a sequence of radii. The radii are centered on the image 
+ *  pixel coordinate x,y, and are defined by the sequence of values in the
+ *  vector radii. The specific algorithm which must be used is described in 
+ *  the PSLib ADD (PSDC-430-006). The statistic used to derive the output 
+ *  vector value is specified by stats. Only one of the statistics choices 
+ *  may be specified, otherwise the function must return an error. This 
+ *  function must be defined for the following types: psS8, psU16, psF32, 
+ *  psF64.
+ *
+ *  @return psVector    resulting vector
+ */
+psVector* psImageRadialCut(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    const psImage* input,              ///< the input image in which to perform the cut
+    const psImage* restrict mask,      ///< the mask for the input image.
+    unsigned int maskVal,              ///< the mask value to apply to the mask
+    float centerCol,                   ///< the column of the center of the cut circle
+    float centerRow,                   ///< the row of the center of the cut circle
+    const psVector* radii,             ///< the radii of the cut circle
+    const psStats* stats               ///< the statistic to perform in operation
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/image/psImageIO.c
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageIO.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageIO.c	(revision 1553)
@@ -0,0 +1,376 @@
+
+/** @file  psImageIO.c
+ *
+ *  @brief Contains image I/O routines.
+ *
+ *  This file defines the file input/output functions for the psImage structure.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <fitsio.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "psImageIO.h"
+#include "psError.h"
+#include "psMemory.h"
+
+psImage* psImageReadSection(psImage* output,
+                            int col,
+                            int row,
+                            int numCols, int numRows, int z, char *extname, int extnum, char *filename)
+{
+    fitsfile *fptr = NULL;      /* Pointer to the FITS file */
+    int status = 0;             /* CFITSIO file vars */
+    int nAxis = 0;
+    int anynull = 0;
+    int bitPix = 0;             /* Pixel type */
+    long nAxes[3];
+    long firstPixel[3];         /* lower-left corner of image subset */
+    long lastPixel[3];          /* upper-right corner of image subset */
+    long increment[3];          /* increment for image subset */
+    char fitsErr[80] = "";      /* CFITSIO error message string */
+    int hduType = IMAGE_HDU;
+    int fitsDatatype = 0;
+    int datatype = 0;
+
+    if (filename == NULL) {
+        psError(__func__, "Must specify filename; it can not be NULL.");
+        psFree(output);
+        return NULL;
+    }
+
+    /* Open the FITS file */
+    (void)fits_open_file(&fptr, filename, READONLY, &status);
+    if (fptr == NULL || status != 0) {
+        fits_get_errstatus(status, fitsErr);
+        psError(__func__, "Could not open file '%s'. (%s)", filename, fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    /* find the specified extension */
+    if (extname != NULL) {
+        if (fits_movnam_hdu(fptr, hduType, extname, 0, &status) != 0) {
+            fits_get_errstatus(status, fitsErr);
+            status = 0;
+            (void)fits_close_file(fptr, &status);
+            psError(__func__, "Could not index to '%s' HDU for file %s. (%s)", extname, filename, fitsErr);
+            psFree(output);
+            return NULL;
+        }
+    } else {
+        if (fits_movabs_hdu(fptr, extnum + 1, &hduType, &status) != 0) {
+            fits_get_errstatus(status, fitsErr);
+            status = 0;
+            (void)fits_close_file(fptr, &status);
+            psError(__func__, "Could not index to HDU #%d for file %s. (%s)", extnum, filename, fitsErr);
+            psFree(output);
+            return NULL;
+        }
+    }
+
+    /* Get the data type 'bitPix' from the FITS image */
+    if (fits_get_img_equivtype(fptr, &bitPix, &status) != 0) {
+        fits_get_errstatus(status, fitsErr);
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError("Could not determine image data type of '%s'. (%s)", filename, fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Get the dimensions 'nAxis' from the FITS image */
+    if (fits_get_img_dim(fptr, &nAxis, &status) != 0) {
+        (void)fits_get_errstatus(status, fitsErr);
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError("Could not determine dimensions of '%s'. (%s)", filename, fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Validate the number of axis */
+    if ((nAxis < 2) || (nAxis > 3)) {
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError("Dimensions of '%s' are not supported (NAXIS=%i).", filename, nAxis);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Get the Image size from the FITS file */
+    if (fits_get_img_size(fptr, nAxis, nAxes, &status) != 0) {
+        (void)fits_get_errstatus(status, fitsErr);
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError("Could not determine image size of '%s'. (%s)", filename, fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    if (numCols < 1) {
+        numCols += nAxes[0] - col;
+    }
+    if (numRows < 1) {
+        numRows += nAxes[1] - row;
+    }
+
+    firstPixel[0] = col + 1;
+    firstPixel[1] = row + 1;
+    firstPixel[2] = z + 1;
+
+    lastPixel[0] = firstPixel[0] + numCols - 1;
+    lastPixel[1] = firstPixel[1] + numRows - 1;
+    lastPixel[2] = z + 1;
+
+    increment[0] = 1;
+    increment[1] = 1;
+    increment[2] = 1;
+
+    // turn off the BSCALE/BZERO processing in
+    // CFITSIO
+    // (void)fits_set_bscale(fptr,
+    // 1.0,0.0,&status);
+
+    switch (bitPix) {
+    case BYTE_IMG:
+        datatype = PS_TYPE_U8;
+        fitsDatatype = TBYTE;
+        break;
+    case SBYTE_IMG:
+        datatype = PS_TYPE_S8;
+        fitsDatatype = TSBYTE;
+        break;
+    case USHORT_IMG:
+        datatype = PS_TYPE_U16;
+        fitsDatatype = TUSHORT;
+        break;
+    case SHORT_IMG:
+        datatype = PS_TYPE_S16;
+        fitsDatatype = TSHORT;
+        break;
+    case ULONG_IMG:
+        datatype = PS_TYPE_U32;
+        fitsDatatype = TUINT;
+        break;
+    case LONG_IMG:
+        datatype = PS_TYPE_S32;
+        fitsDatatype = TINT;
+        break;
+    case LONGLONG_IMG:
+        datatype = PS_TYPE_S64;
+        fitsDatatype = TLONGLONG;
+        break;
+    case FLOAT_IMG:
+        datatype = PS_TYPE_F32;
+        fitsDatatype = TFLOAT;
+        break;
+    case DOUBLE_IMG:
+        datatype = PS_TYPE_F64;
+        fitsDatatype = TDOUBLE;
+        break;
+    default:
+        psError(__func__, "Unsupported bitpix value (%d) in FITS file %s.", bitPix, filename);
+        psFree(output);
+        return NULL;
+    }
+    output = psImageRecycle(output, numCols, numRows, datatype);
+    if (fits_read_subset
+            (fptr, fitsDatatype, firstPixel,
+             lastPixel, increment, NULL, output->data.V[0], &anynull, &status) != 0) {
+        psFree(output);
+        (void)fits_get_errstatus(status, fitsErr);
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError(__func__, "Failed to read image [%s]", filename, fitsErr);
+        return NULL;
+    }
+
+    (void)fits_close_file(fptr, &status);
+
+    return output;
+}
+
+bool psImageWriteSection(psImage* input, int col0, int row0, int z, char *extname, int extnum,
+                         char *filename)
+{
+    int numCols = 0;
+    int numRows = 0;
+
+    int status = 0;             /* CFITSIO status */
+    fitsfile *fptr = NULL;      /* pointer to the FITS file */
+    long nAxes[3];              /* Image axis vars */
+    long firstPixel[3];         /* First Pixel to read */
+    long lastPixel[3];          /* Last Pixel to read */
+    char fitsErr[80];           /* FITSIO message string */
+    int datatype = 0;           /* the datatype of the image */
+    int bitPix = 0;             /* FITS bitPix value */
+    int hduType = IMAGE_HDU;    /* the HDU type (image,table, etc.) */
+    double bscale = 1.0;
+    double bzero = 0.0;
+    bool createNewHDU = false;
+
+    /* need a valid image to write */
+    if (input == NULL) {
+        psError(__func__, "Can not write %s.  Input psImage is NULL.", filename);
+        return false;
+    }
+
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    switch (input->type.type) {
+    case PS_TYPE_U8:
+        bitPix = BYTE_IMG;
+        datatype = TBYTE;
+        break;
+    case PS_TYPE_S8:
+        bitPix = BYTE_IMG;
+        bzero = INT8_MIN;
+        datatype = TSBYTE;
+        break;
+    case PS_TYPE_U16:
+        bitPix = SHORT_IMG;
+        bzero = -1.0f * INT16_MIN;
+        datatype = TUSHORT;
+        break;
+    case PS_TYPE_S16:
+        bitPix = SHORT_IMG;
+        datatype = TSHORT;
+        break;
+    case PS_TYPE_U32:
+        bitPix = LONG_IMG;
+        bzero = -1.0f * INT32_MIN;
+        datatype = TUINT;
+        break;
+    case PS_TYPE_S32:
+        bitPix = LONG_IMG;
+        datatype = TINT;
+        break;
+    case PS_TYPE_F32:
+        bitPix = FLOAT_IMG;
+        datatype = TFLOAT;
+        break;
+    case PS_TYPE_F64:
+        bitPix = DOUBLE_IMG;
+        datatype = TDOUBLE;
+        break;
+    default:
+        psError(__func__,
+                "psImage datatype (%d) not supported.  File %s not written.", input->type.type, filename);
+        return false;
+    }
+
+    /* Open the FITS file */
+    if (access(filename, F_OK) == 0) {     // file
+        // exists
+        (void)fits_open_file(&fptr, filename, READWRITE, &status);
+        if (fptr == NULL || status != 0) {
+            fits_get_errstatus(status, fitsErr);
+            psError(__func__, "Could not open file '%s'. FITS error:%s", filename, fitsErr);
+            return false;
+        }
+
+        /* find the specified extension */
+        if (extname != NULL) {
+            if (fits_movnam_hdu(fptr, hduType, extname, 0, &status) != 0) {
+                fits_get_errstatus(status, fitsErr);
+                status = 0;
+                (void)fits_close_file(fptr, &status);
+                psError(__func__,
+                        "Could not index to '%s' HDU for file %s. (%s)", extname, filename, fitsErr);
+                return false;
+            }
+        } else {
+            int numHDUs = 0;
+
+            fits_get_num_hdus(fptr, &numHDUs, &status);
+            if (numHDUs < extnum) {
+                status = 0;
+                (void)fits_close_file(fptr, &status);
+                psError(__func__,
+                        "extnum (%d) must not exceed number of HDUs (%d) by more than one.", extnum, numHDUs);
+                return false;
+            } else if (numHDUs == extnum) {
+                createNewHDU = true;
+            } else if (fits_movabs_hdu(fptr, extnum + 1, &hduType, &status) != 0) {
+                fits_get_errstatus(status, fitsErr);
+                status = 0;
+                (void)fits_close_file(fptr, &status);
+                psError(__func__, "Could not index to HDU #%d for file %s. (%s)", extnum, filename, fitsErr);
+                return false;
+            }
+        }
+
+    } else {                               // file
+        // does
+        // not
+        // exist
+
+        (void)fits_create_file(&fptr, filename, &status);
+        if (fptr == NULL || status != 0) {
+            fits_get_errstatus(status, fitsErr);
+            psError(__func__, "Could not create file '%s'. (%s)", filename, fitsErr);
+            return false;
+        }
+        createNewHDU = true;
+    }
+
+    if (createNewHDU) {
+        /* create the mandatory image keywords */
+        nAxes[0] = col0 + numCols;
+        nAxes[1] = row0 + numRows;
+        nAxes[2] = z + 1;
+        if (fits_create_img(fptr, bitPix, 3, nAxes, &status) != 0) {
+            (void)fits_get_errstatus(status, fitsErr);
+            status = 0;
+            (void)fits_close_file(fptr, &status);
+            psError(__func__, "Could not create image HDU in FITS file '%s'. %s", filename, fitsErr);
+            return false;
+        }
+        // set the bscale/bzero
+        fits_write_key_dbl(fptr, "BZERO", bzero, 12, "Pixel Value Offset", &status);
+        fits_write_key_dbl(fptr, "BSCALE", bscale, 12, "Pixel Value Scale", &status);
+        fits_set_bscale(fptr, bscale, bzero, &status);
+
+        if (extname != NULL) {
+            /* create the extension for the Primary HDU */
+            if (fits_write_key_str(fptr, "EXTNAME", extname, "Extension Name", &status) != 0) {
+                (void)fits_get_errstatus(status, fitsErr);
+                status = 0;
+                (void)fits_close_file(fptr, &status);
+                psError(__func__,
+                        "Could not create EXTNAME keyword in FITS file '%s'. (%s)", filename, fitsErr);
+                return false;
+            }
+        }
+    }
+
+    firstPixel[0] = col0 + 1;
+    firstPixel[1] = row0 + 1;
+    firstPixel[2] = z + 1;
+
+    lastPixel[0] = firstPixel[0] + numCols - 1;
+    lastPixel[1] = firstPixel[1] + numRows - 1;
+    lastPixel[2] = z + 1;
+
+    if (fits_write_subset(fptr, datatype, firstPixel, lastPixel, input->data.V[0], &status) != 0) {
+        (void)fits_get_errstatus(status, fitsErr);
+        status = 0;
+        (void)fits_close_file(fptr, &status);
+        psError(__func__, "Could not write image data to '%s'. (%s)", filename, fitsErr);
+        return false;
+    }
+
+    status = 0;
+    (void)fits_close_file(fptr, &status);
+
+    return true;
+}
Index: /tags/rel2_1/psLib/src/image/psImageIO.h
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageIO.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageIO.h	(revision 1553)
@@ -0,0 +1,98 @@
+
+/** @file  psImageIO.h
+ *
+ *  @brief Contains image input/output routines
+ *
+ *  This file defines the file input/output functions for the psImage structure.
+ *
+ *  @ingroup ImageIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:05:53 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGEIO_H
+#define PS_IMAGEIO_H
+
+#include <stdbool.h>
+
+#include "psImage.h"
+
+/// @addtogroup ImageIO
+/// @{
+
+/** Read an image or subimage from a FITS file specified by a filename.
+ *
+ *  return psImage* The image read from the specified file.  NULL
+ *                          signifies that a problem had occured.
+ */
+psImage* psImageReadSection(
+    psImage* output,
+    /**< the output psImage to recycle, or NULL if new psImage desired */
+
+    int col0,
+    /**< the column index of the origin to start reading */
+
+    int row0,
+    /**< the row index of the origin to start reading */
+
+    int numCols,
+    /**< the number of desired columns to read */
+
+    int numRows,
+    /**< the number of desired rows to read */
+
+    int z,
+    /**< the z index to read if file is organized as a 3D image cube. */
+
+    char *extname,
+    /**< the image extension to read (this should match the EXTNAME keyword in
+        *   the extension If NULL, the extnum parameter is to be used instead
+        */
+
+    int extnum,
+    /**< the image extension to read (0=PHU, 1=first extension, etc.)  This is
+        *   only used if extname is NULL
+        */
+
+    char *filename
+    /**< the filename of the FITS image file to read */
+);
+
+/** Read an image or subimage from a FITS file specified by a filename.
+ *
+ *  return bool         TRUE is successful, otherwise FALSE.
+ */
+bool psImageWriteSection(
+    psImage* input,
+    /**< the psImage to write */
+
+    int col0,
+    /**< the column index of the origin to start writing */
+
+    int row0,
+    /**< the row index of the origin to start writing */
+
+    int z,
+    /**< the z index to start writing */
+
+    char *extname,
+    /**< the image extension to write (this should match the EXTNAME keyword in
+    *   the extension If NULL, the extnum parameter is to be used instead
+    */
+
+    int extnum,
+    /**< the image extension to write (0=PHU, 1=first extension, etc.)  This is
+    *   only used if extname is NULL.
+    */
+
+    char *filename
+    /**< the filename of the FITS image file to write */
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/image/psImageManip.c
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageManip.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageManip.c	(revision 1553)
@@ -0,0 +1,867 @@
+
+/** @file  psImageManip.c
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Image Pixel Manipulations" and
+ *         "Image Geometry Manipulations".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-13 00:02:03 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <math.h>                          // for
+// isfinite(),
+// etc.
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>                        // for
+// memcpy,
+// etc.
+
+#include "psError.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psMemory.h"
+#include "psImageExtraction.h"
+
+int psImageClip(psImage* input, psF64 min, psF64 vmin, psF64 max, psF64 vmax)
+{
+    int numClipped = 0;
+    unsigned int numRows;
+    unsigned int numCols;
+
+    if (input == NULL) {
+        return 0;
+    }
+
+    if (max < min) {
+        psError(__func__, "psImageClip can not be invoked with max < min.");
+        return 0;
+    }
+
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    switch (input->type.type) {
+
+        #define psImageClipCase(type,typename) \
+    case PS_TYPE_##type: { \
+            if (vmin < PS_MIN_##type || vmin > PS_MAX_##type) { \
+                psError(__func__, "Specified vmin (%g) is outside of image's " \
+                        typename " pixel range (%g to %g)", \
+                        vmin,(psF64)PS_MIN_##type,(psF64)PS_MAX_##type); \
+            } \
+            if (vmax > PS_MAX_##type || vmax < PS_MIN_##type) { \
+                psError(__func__, "Specified vmax (%g) is outside of image's " \
+                        typename " pixel range (%g to %g)", \
+                        vmax,(psF64)PS_MIN_##type,(psF64)PS_MAX_##type); \
+            } \
+            for (unsigned int row = 0;row<numRows;row++) { \
+                ps##type* inputRow = input->data.type[row]; \
+                for (unsigned int col = 0; col < numCols; col++) { \
+                    if ((psF64)inputRow[col] < min) { \
+                        inputRow[col] = (ps##type)vmin; \
+                        numClipped++; \
+                    } else if ((psF64)inputRow[col] > max) { \
+                        inputRow[col] = (ps##type)vmax; \
+                        numClipped++; \
+                    } \
+                } \
+            } \
+        } \
+        break;
+
+        #define psImageClipCaseComplex(type,typename,absfcn)\
+    case PS_TYPE_##type: { \
+            if (vmin < PS_MIN_##type || vmin > PS_MAX_##type) { \
+                psError(__func__, "Specified vmin (%g) is outside of image's " \
+                        typename " pixel range", \
+                        vmin); \
+            } \
+            if (vmax > PS_MAX_##type || vmax < PS_MIN_##type) { \
+                psError(__func__, "Specified vmax (%g) is outside of image's " \
+                        typename " pixel range", \
+                        vmax); \
+            } \
+            for (unsigned int row = 0;row<numRows;row++) { \
+                ps##type* inputRow = input->data.type[row]; \
+                for (unsigned int col = 0; col < numCols; col++) { \
+                    if (absfcn(inputRow[col]) < min) { \
+                        inputRow[col] = (ps##type)vmin; \
+                        numClipped++; \
+                    } else if (absfcn(inputRow[col]) > max) { \
+                        inputRow[col] = (ps##type)vmax; \
+                        numClipped++; \
+                    } \
+                } \
+            } \
+        } \
+        break;
+
+        psImageClipCase(S8, "psS8")
+        psImageClipCase(S16, "psS16")
+        psImageClipCase(S32, "psS32")
+        psImageClipCase(S64, "psS64")
+        psImageClipCase(U8, "psU8")
+        psImageClipCase(U16, "psU16")
+        psImageClipCase(U32, "psU32")
+        psImageClipCase(U64, "psU64")
+        psImageClipCase(F32, "psF32")
+        psImageClipCase(F64, "psF64")
+        psImageClipCaseComplex(C32, "psC32", cabsf)
+        psImageClipCaseComplex(C64, "psC64", cabs)
+
+    default:
+        psError(__func__, "psImageClip does not support the given datatype (%d)", input->type.type);
+    }
+
+    return numClipped;
+}
+
+int psImageClipNaN(psImage* input, psF64 value)
+{
+    int numClipped = 0;
+    unsigned int numRows;
+    unsigned int numCols;
+
+    if (input == NULL) {
+        return 0;
+    }
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    switch (input->type.type) {
+
+        #define psImageClipNaNCase(type) \
+    case PS_TYPE_##type: \
+        for (unsigned int row = 0;row<numRows;row++) { \
+            ps##type* inputRow = input->data.type[row]; \
+            for (unsigned int col = 0; col < numCols; col++) { \
+                if (! isfinite(inputRow[col])) { \
+                    inputRow[col] = (ps##type)value; \
+                    numClipped++; \
+                } \
+            } \
+        } \
+        break;
+
+        psImageClipNaNCase(F32)
+        psImageClipNaNCase(F64)
+        psImageClipNaNCase(C32)
+        psImageClipNaNCase(C64)
+
+    default:
+        psError(__func__, "psImageClip does not support the given datatype (%d)", input->type.type);
+    }
+
+    return numClipped;
+}
+
+int psImageOverlaySection(psImage* image, const psImage* overlay, int col0, int row0, const char *op)
+{
+    unsigned int imageNumRows;
+    unsigned int imageNumCols;
+    unsigned int overlayNumRows;
+    unsigned int overlayNumCols;
+    unsigned int imageRowLimit;
+    unsigned int imageColLimit;
+    psElemType type;
+
+    if (image == NULL || overlay == NULL) {
+        psError(__func__, "one of the input images was NULL.");
+        return 1;
+    }
+
+    if (op == NULL) {
+        psError(__func__, "Operation can not be NULL.");
+        return 1;
+    }
+
+    type = image->type.type;
+
+    if (type != overlay->type.type) {
+        psError(__func__, "Image and overlay datatypes must match. (%d vs %d)", type, overlay->type.type);
+        return 2;
+    }
+
+    imageNumRows = image->numRows;
+    imageNumCols = image->numCols;
+    overlayNumRows = overlay->numRows;
+    overlayNumCols = overlay->numCols;
+
+    /* check row0/col0 to see if it is within the image size */
+    if (row0 < 0 || col0 < 0 || row0 >= imageNumRows || col0 >= imageNumCols) {
+        psError(__func__,
+                "Overlay origin of (%d,%d) is outside of the image dimensions (%d x %d).",
+                col0, row0, imageNumCols, imageNumRows);
+        return 3;
+    }
+
+    /* check if overlay is totally withing input image */
+    imageRowLimit = row0 + overlayNumRows;
+    imageColLimit = col0 + overlayNumCols;
+    if (imageRowLimit > imageNumRows || imageColLimit > imageNumCols) {
+        psError(__func__,
+                "Overlay image (%d,%d -> %d,%d) is partially outside"
+                " of the input image (%d x %d).",
+                col0, row0, col0 + overlayNumCols - 1, row0 + overlayNumRows - 1, imageNumCols, imageNumRows);
+        return 4;
+    }
+
+    switch (type) {
+
+        #define psImageOverlayCase(DATATYPE) \
+    case PS_TYPE_##DATATYPE: \
+        for (unsigned int row=row0;row<imageRowLimit;row++) { \
+            ps##DATATYPE* imageRow = image->data.DATATYPE[row]; \
+            ps##DATATYPE* overlayRow = overlay->data.DATATYPE[row-row0]; \
+            for (unsigned int col=col0;col<imageColLimit;col++) { \
+                switch (*op) { \
+                case '+': \
+                    imageRow[col] += overlayRow[col-col0]; \
+                    break; \
+                case '-': \
+                    imageRow[col] -= overlayRow[col-col0]; \
+                    break; \
+                case '*': \
+                    imageRow[col] *= overlayRow[col-col0]; \
+                    break; \
+                case '/': \
+                    imageRow[col] /= overlayRow[col-col0]; \
+                    break; \
+                case '=': \
+                    imageRow[col] = overlayRow[col-col0]; \
+                    break; \
+                default: \
+                    psError(__func__,"Unknown operation %s",op); \
+                    return 5; \
+                } \
+            } \
+        } \
+        break;
+
+        psImageOverlayCase(U8);
+        psImageOverlayCase(U16);
+        psImageOverlayCase(U32);
+        psImageOverlayCase(U64);
+        psImageOverlayCase(S8);
+        psImageOverlayCase(S16);
+        psImageOverlayCase(S32);
+        psImageOverlayCase(S64);
+        psImageOverlayCase(F32);
+        psImageOverlayCase(F64);
+        psImageOverlayCase(C32);
+        psImageOverlayCase(C64);
+
+    default:
+        psError(__func__, "Can not operate on type %d.", type);
+    }
+
+    return 0;
+}
+
+int psImageClipComplexRegion(psImage* input, psC64 min, psC64 vmin, psC64 max, psC64 vmax)
+{
+    int numClipped = 0;
+    unsigned int numRows;
+    unsigned int numCols;
+    psF64 realMin = creal(min);
+    psF64 imagMin = cimag(min);
+    psF64 realMax = creal(max);
+    psF64 imagMax = cimag(max);
+
+    if (input == NULL) {
+        psError(__func__, "Can not perform clip on NULL image");
+        return 0;
+    }
+
+    if (realMax < realMin) {
+        psError(__func__,
+                "psImageClipComplexRegion can not be invoked with " "max < min in the real image space.");
+        return 0;
+    }
+    if (imagMax < imagMin) {
+        psError(__func__,
+                "psImageClipComplexRegion can not be invoked with "
+                "max < min in the imaginary image space.");
+        return 0;
+    }
+
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    #define psImageClipComplexRegionCase(type,typename,realfcn,imagfcn) \
+case PS_TYPE_##type: { \
+        if (realfcn(vmin) < PS_MIN_##type || imagfcn(vmin) < PS_MIN_##type || \
+                realfcn(vmin) > PS_MAX_##type || imagfcn(vmin) > PS_MAX_##type ) { \
+            psError(__func__, "Specified vmin (%g%+gi) is outside of image's " \
+                    typename " pixel range", \
+                    creal(vmin),cimag(vmin)); \
+            break; \
+        } \
+        if (realfcn(vmax) > PS_MAX_##type || imagfcn(vmax) > PS_MAX_##type || \
+                realfcn(vmax) < PS_MIN_##type || imagfcn(vmax) < PS_MIN_##type ) { \
+            psError(__func__, "Specified vmax (%g%+gi) is outside of image's " \
+                    typename " pixel range", \
+                    creal(vmax),cimag(vmax)); \
+            break; \
+        } \
+        for (unsigned int row = 0;row<numRows;row++) { \
+            ps##type* inputRow = input->data.type[row]; \
+            for (unsigned int col = 0; col < numCols; col++) { \
+                if ( (realfcn(inputRow[col]) > realMax) || (imagfcn(inputRow[col]) > imagMax) ) { \
+                    inputRow[col] = (ps##type)vmax; \
+                    numClipped++; \
+                } else if ( (realfcn(inputRow[col]) < realMin) || (imagfcn(inputRow[col]) < imagMin) ){ \
+                    inputRow[col] = (ps##type)vmin; \
+                    numClipped++; \
+                } \
+            } \
+        } \
+    } \
+    break;
+
+    switch (input->type.type) {
+
+        psImageClipComplexRegionCase(C32, "psC32", crealf, cimagf)
+        psImageClipComplexRegionCase(C64, "psC64", creal, cimag)
+
+    default:
+        psError(__func__, "psImageClip does not support the given datatype (%d)", input->type.type);
+    }
+
+    return numClipped;
+}
+
+psImage* psImageRebin(psImage* out, const psImage* in, unsigned int scale, const psStats* stats)
+{
+    int inRows;
+    int inCols;
+    int outRows;
+    int outCols;
+    psVector* vec;              // vector to hold
+
+    // the values of
+    // a single bin.
+    psStats* myStats;
+    double statVal;
+
+    if (in == NULL) {
+        psError(__func__, "Input image is NULL.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (scale < 1) {
+        psError(__func__, "The scale must be positive.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (stats == NULL) {
+        psError(__func__, "The stats input can not be NULL.");
+        psFree(out);
+        return NULL;
+    }
+
+    if (p_psGetStatValue(stats, &statVal) == false) {
+        psError(__func__, "The stat options didn't specify a single supported statistic type.");
+        psFree(out);
+        return NULL;
+    }
+
+    myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    vec = psVectorAlloc(scale * scale, in->type.type);
+
+    // create output image.
+    inRows = in->numRows;
+    inCols = in->numCols;
+    outRows = (inRows + scale - 1) / scale;     // round-up
+    // for
+    // remainders
+    outCols = (inCols + scale - 1) / scale;     // round-up
+    // for
+    // remainders
+    out = psImageRecycle(out, outCols, outRows, in->type.type);
+
+    #define PS_IMAGE_REBIN_CASE(type) \
+case PS_TYPE_##type: { \
+        ps##type* vecData = vec->data.type; \
+        for (int row = 0; row < outRows; row++) { \
+            ps##type* outRowData = out->data.type[row]; \
+            int inCurrentRow = row*scale; \
+            int inNextRow = (row+1)*scale; \
+            for (int col = 0; col < outCols; col++) { \
+                int inCurrentCol = col*scale; \
+                int inNextCol = (col+1)*scale; \
+                int n = 0; \
+                for (int inRow = inCurrentRow; inRow < inNextRow && inRow < inRows; inRow++) { \
+                    ps##type* inRowData = in->data.type[inRow]; \
+                    for (int inCol = inCurrentCol; inCol < inNextCol && inCol < inCols; inCol++) { \
+                        vecData[n++] = inRowData[inCol]; \
+                    } \
+                } \
+                vec->n = n; \
+                myStats = psVectorStats(myStats,vec,NULL,0); \
+                p_psGetStatValue(myStats,&statVal); \
+                outRowData[col] = (ps##type)statVal; \
+            } \
+        } \
+    } \
+    break;
+
+    switch (in->type.type) {
+        PS_IMAGE_REBIN_CASE(U8);
+        PS_IMAGE_REBIN_CASE(U16);
+        PS_IMAGE_REBIN_CASE(U32);
+        PS_IMAGE_REBIN_CASE(U64);
+        PS_IMAGE_REBIN_CASE(S8);
+        PS_IMAGE_REBIN_CASE(S16);
+        PS_IMAGE_REBIN_CASE(S32);
+        PS_IMAGE_REBIN_CASE(S64);
+        PS_IMAGE_REBIN_CASE(F32);
+        PS_IMAGE_REBIN_CASE(F64);
+        PS_IMAGE_REBIN_CASE(C32);
+        PS_IMAGE_REBIN_CASE(C64);
+    default:
+        psError(__func__, "Input image type not supported.");
+        psFree(out);
+        out = NULL;
+    }
+
+    psFree(vec);
+    psFree(myStats);
+
+    return out;
+}
+
+psImage* psImageResample(psImage* out, const psImage* in, int scale, psImageInterpolateMode mode)
+{
+    int outRows;
+    int outCols;
+    float invScale;
+
+    if (in == NULL) {
+        psError(__func__, "Input image can not be NULL.");
+        psFree(out);
+        return NULL;
+    }
+    // create an output image of the same size
+    // and type
+    outRows = in->numRows * scale;
+    outCols = in->numCols * scale;
+    invScale = 1.0f / (float)scale;
+
+    #define PSIMAGE_RESAMPLE_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        out = psImageRecycle(out,outCols, outRows, PS_TYPE_##TYPE); \
+        for (int row=0;row<outRows;row++) { \
+            ps##TYPE* rowData = out->data.TYPE[row]; \
+            float inRow = (float)row * invScale; \
+            for (int col=0;col<outCols;col++) { \
+                rowData[col] = psImagePixelInterpolate(in,inRow,(float)col*invScale,0,mode); \
+            } \
+        }  \
+        break; \
+    }
+
+    switch (in->type.type) {
+        PSIMAGE_RESAMPLE_CASE(U8)
+        PSIMAGE_RESAMPLE_CASE(U16)
+        PSIMAGE_RESAMPLE_CASE(U32)
+        PSIMAGE_RESAMPLE_CASE(U64)
+        PSIMAGE_RESAMPLE_CASE(S8)
+        PSIMAGE_RESAMPLE_CASE(S16)
+        PSIMAGE_RESAMPLE_CASE(S32)
+        PSIMAGE_RESAMPLE_CASE(S64)
+        PSIMAGE_RESAMPLE_CASE(F32)
+        PSIMAGE_RESAMPLE_CASE(F64)
+        PSIMAGE_RESAMPLE_CASE(C32)
+        PSIMAGE_RESAMPLE_CASE(C64)
+    default:
+        psError(__func__, "Unsupported type (%d)", in->type.type);
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+psImage* psImageRoll(psImage* out, const psImage* in, int dx, int dy)
+{
+    int outRows;
+    int outCols;
+    int elementSize;
+
+    if (in == NULL) {
+        psError(__func__, "Input image can not be NULL.");
+        psFree(out);
+        return NULL;
+    }
+    // create an output image of the same size
+    // and type
+    outRows = in->numRows;
+    outCols = in->numCols;
+    elementSize = PSELEMTYPE_SIZEOF(in->type.type);
+    out = psImageRecycle(out, outCols, outRows, in->type.type);
+
+    // make dx and dy between 0 and outCols or
+    // outRows, respectively
+    dx = dx % outCols;
+    dy = dy % outRows;
+    if (dx < 0) {
+        dx += outCols;
+    }
+    if (dy < 0) {
+        dy += outRows;
+    }
+
+    int segment1Size = elementSize * (outCols - dx);
+    int segment2Size = elementSize * dx;
+
+    for (int row = 0; row < outRows; row++) {
+        int inRowNumber = row + dy;
+
+        if (inRowNumber >= outRows) {
+            inRowNumber -= outRows;
+        }
+        psU8* inRow = in->data.U8[inRowNumber]; // to
+
+        // allow
+
+        // byte
+        // arithmetic,
+
+        // but for all types
+        psU8* outRow = out->data.U8[row];
+
+        memcpy(outRow, inRow + segment2Size, segment1Size);
+        memcpy(outRow + segment1Size, inRow, segment2Size);
+    }
+
+    return out;
+}
+
+psImage* psImageRotate(psImage* out,
+                       const psImage* in,
+                       float angle,
+                       float unexposedValue,
+                       psImageInterpolateMode mode)
+{
+    if (in == NULL) {
+        psError(__func__, "The input image was NULL.");
+        psFree(out);
+        return NULL;
+    }
+    // put the angle in the range of 0...360.
+    angle = angle - 360.0f * floor(angle / 360.0f);
+
+    if (fabsf(angle - 90.0f) < FLT_EPSILON) {
+        // perform 1/4 rotate counter-clockwise
+        int numRows = in->numCols;
+        int numCols = in->numRows;
+        int lastCol = numCols - 1;
+        psElemType type = in->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_LEFT_90(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            ps##TYPE** inData = in->data.TYPE; \
+            for (int row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                for (int col=0;col<numCols;col++) { \
+                    outRow[col] = inData[lastCol-col][row]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_LEFT_90(U8);
+            PSIMAGE_ROTATE_LEFT_90(U16);
+            PSIMAGE_ROTATE_LEFT_90(U32);
+            PSIMAGE_ROTATE_LEFT_90(U64);
+            PSIMAGE_ROTATE_LEFT_90(S8);
+            PSIMAGE_ROTATE_LEFT_90(S16);
+            PSIMAGE_ROTATE_LEFT_90(S32);
+            PSIMAGE_ROTATE_LEFT_90(S64);
+            PSIMAGE_ROTATE_LEFT_90(F32);
+            PSIMAGE_ROTATE_LEFT_90(F64);
+            PSIMAGE_ROTATE_LEFT_90(C32);
+            PSIMAGE_ROTATE_LEFT_90(C64);
+        default:
+            psError(__func__, "Unsupported type (%d)", type);
+            psFree(out);
+            return NULL;
+        }
+    } else if (fabsf(angle - 180.0f) < FLT_EPSILON) {
+        // perform 1/2 rotate
+        int numRows = in->numRows;
+        int lastRow = numRows - 1;
+        int numCols = in->numCols;
+        int lastCol = numCols - 1;
+        psElemType type = in->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_180_CASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            for (int row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                ps##TYPE* inRow = in->data.TYPE[lastRow-row]; \
+                for (int col=0;col<numCols;col++) { \
+                    outRow[col] = inRow[lastCol - col]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_180_CASE(U8);
+            PSIMAGE_ROTATE_180_CASE(U16);
+            PSIMAGE_ROTATE_180_CASE(U32);
+            PSIMAGE_ROTATE_180_CASE(U64);
+            PSIMAGE_ROTATE_180_CASE(S8);
+            PSIMAGE_ROTATE_180_CASE(S16);
+            PSIMAGE_ROTATE_180_CASE(S32);
+            PSIMAGE_ROTATE_180_CASE(S64);
+            PSIMAGE_ROTATE_180_CASE(F32);
+            PSIMAGE_ROTATE_180_CASE(F64);
+            PSIMAGE_ROTATE_180_CASE(C32);
+            PSIMAGE_ROTATE_180_CASE(C64);
+        default:
+            psError(__func__, "Unsupported type (%d)", type);
+            psFree(out);
+            return NULL;
+        }
+    } else if (fabsf(angle - 270.0f) < FLT_EPSILON) {
+        // perform 1/4 rotate clockwise
+        int numRows = in->numCols;
+        int lastRow = numRows - 1;
+        int numCols = in->numRows;
+        psElemType type = in->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_RIGHT_90(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            ps##TYPE** inData = in->data.TYPE; \
+            for (int row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                for (int col=0;col<numCols;col++) { \
+                    outRow[col] = inData[col][lastRow-row]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_RIGHT_90(U8);
+            PSIMAGE_ROTATE_RIGHT_90(U16);
+            PSIMAGE_ROTATE_RIGHT_90(U32);
+            PSIMAGE_ROTATE_RIGHT_90(U64);
+            PSIMAGE_ROTATE_RIGHT_90(S8);
+            PSIMAGE_ROTATE_RIGHT_90(S16);
+            PSIMAGE_ROTATE_RIGHT_90(S32);
+            PSIMAGE_ROTATE_RIGHT_90(S64);
+            PSIMAGE_ROTATE_RIGHT_90(F32);
+            PSIMAGE_ROTATE_RIGHT_90(F64);
+            PSIMAGE_ROTATE_RIGHT_90(C32);
+            PSIMAGE_ROTATE_RIGHT_90(C64);
+        default:
+            psError(__func__, "Unsupported type (%d)", type);
+            psFree(out);
+            return NULL;
+        }
+    } else if (fabsf(angle) < FLT_EPSILON) {
+        out = psImageCopy(out, in, in->type.type);
+    } else {
+        psElemType type = in->type.type;
+        int numRows = in->numRows;
+        int numCols = in->numCols;
+        double centerX = (float)(numCols) / 2.0f;
+        float centerY = (float)(numRows) / 2.0f;
+        float t = angle * (3.14159265358f / 180.0f);
+        double cosT = cosf(t);
+        double sinT = sinf(t);
+
+        // calculate the corners of the rotated
+        // image so we know the proper
+        // output image size.
+        // x' = x cos(t) + y sin(t); i.e, x' =
+        // (x-centerX)*cosT +
+        // (y-centerY)*sinT;
+        // y' = y cos(t) - x sin(t); i.e. y' =
+        // (y-centerY)*cosT -
+        // (x-centerX)*sinT;
+
+        int outCols = ceil(abs(numCols * cosT) + abs(numRows * sinT)) + 1;
+        int outRows = ceil(abs(numCols * sinT) + abs(numRows * cosT)) + 1;
+        float minX = (float)outCols / -2.0f;
+        int intMinY = outRows / -2;
+
+        out = psImageRecycle(out, outCols, outRows, type);
+
+        /* optimized public domain rotation routine by Karl Lager float cosT,sinT; cosT = cos(t); sinT =
+         * sin(t); for (y = min_y; y <= max_y; y++) { x' = min_x * cosT + y * sinT + x1'; y' = y * cosT -
+         * min_x * sinT + y1'; for (x = min_x; x <= max_x; x++) { if (x', y') * * * * * * * * is in the
+         * bounds of the bitmap, get pixel(x', y') and plot the pixel to (x, y) on screen. x' += cosT; y' -=
+         * sinT; } } */
+
+        // precalculate some figures that are
+        // used within loop
+        float minXTimesCosTPlusCenterX = minX * cosT + centerX;
+        float CenterYMinusminXTimesSinT = centerY - minX * sinT;
+
+        #define PSIMAGE_ROTATE_ARBITRARY_LOOP(TYPE,MODE) { \
+            if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \
+                psError(__func__,"The given unexposedValue (%g) is outside of the " \
+                        "image type's range (%g->%g).", \
+                        unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
+                psFree(out); \
+                out = NULL; \
+                break; \
+            } \
+            float inX; \
+            float inY; \
+            ps##TYPE* outRow; \
+            for (int y = 0; y < outRows; y++) { \
+                inX = minXTimesCosTPlusCenterX + (y+intMinY) * sinT; \
+                inY = CenterYMinusminXTimesSinT + (y+intMinY) * cosT; \
+                outRow = out->data.TYPE[y]; \
+                for (int x = 0; x < outCols; x++) { \
+                    outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,unexposedValue); \
+                    inX += cosT; \
+                    inY -= sinT; \
+                } \
+            } \
+        }
+
+        #define PSIMAGE_ROTATE_ARBITRARY_CASE(MODE) \
+    case PS_INTERPOLATE_##MODE: \
+        switch (type) { \
+        case PS_TYPE_U8: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U8,MODE); \
+            break; \
+        case PS_TYPE_U16: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U16,MODE); \
+            break; \
+        case PS_TYPE_U32: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U32,MODE); \
+            break; \
+        case PS_TYPE_U64: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U64,MODE); \
+            break; \
+        case PS_TYPE_S8: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S8,MODE); \
+            break; \
+        case PS_TYPE_S16: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S16,MODE); \
+            break; \
+        case PS_TYPE_S32: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S32,MODE); \
+            break; \
+        case PS_TYPE_S64: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S64,MODE); \
+            break; \
+        case PS_TYPE_F32: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(F32,MODE); \
+            break; \
+        case PS_TYPE_F64: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(F64,MODE); \
+            break; \
+        case PS_TYPE_C32: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(C32,MODE); \
+            break; \
+        case PS_TYPE_C64: \
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(C64,MODE); \
+            break; \
+        default: \
+            psError(__func__,"Image type (%d) not supported",type); \
+            psFree(out); \
+            out = NULL; \
+        } \
+        break;
+
+        switch (mode) {
+            PSIMAGE_ROTATE_ARBITRARY_CASE(FLAT);
+            PSIMAGE_ROTATE_ARBITRARY_CASE(BILINEAR);
+        default:
+            psError(__func__, "Unsupported interpolation mode (%d)", mode);
+            psFree(out);
+            out = NULL;
+        }
+    }
+
+    return out;
+}
+
+psImage* psImageShift(psImage* out,
+                      const psImage* in,
+                      float dx, float dy, psF64 unexposedValue, psImageInterpolateMode mode)
+{
+    int outRows;
+    int outCols;
+    int elementSize;
+    psElemType type;
+
+    if (in == NULL) {
+        psError(__func__, "Input image can not be NULL.");
+        return NULL;
+    }
+    // create an output image of the same size
+    // and type
+    outRows = in->numRows;
+    outCols = in->numCols;
+    type = in->type.type;
+    elementSize = PSELEMTYPE_SIZEOF(type);
+    out = psImageRecycle(out, outCols, outRows, type);
+
+    #define PSIMAGE_SHIFT_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \
+        psError(__func__,"The given unexposedValue (%g) is outside of the " \
+                "image type's range (%g->%g).", \
+                unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
+        psFree(out); \
+        out = NULL; \
+        break; \
+    } \
+    for (int row=0;row<outRows;row++) { \
+        ps##TYPE* outRow = out->data.TYPE[row]; \
+        float y = dy+(float)row; \
+        for (int col=0;col<outCols;col++) { \
+            outRow[col] = psImagePixelInterpolate(in,dx+(float)col,y,unexposedValue,mode); \
+        } \
+    } \
+    break;
+
+    switch (in->type.type) {
+        PSIMAGE_SHIFT_CASE(U8);
+        PSIMAGE_SHIFT_CASE(U16);
+        PSIMAGE_SHIFT_CASE(U32);
+        PSIMAGE_SHIFT_CASE(U64);
+        PSIMAGE_SHIFT_CASE(S8);
+        PSIMAGE_SHIFT_CASE(S16);
+        PSIMAGE_SHIFT_CASE(S32);
+        PSIMAGE_SHIFT_CASE(S64);
+        PSIMAGE_SHIFT_CASE(F32);
+        PSIMAGE_SHIFT_CASE(F64);
+        PSIMAGE_SHIFT_CASE(C32);
+        PSIMAGE_SHIFT_CASE(C64);
+    default:
+        psError(__func__, "Image type (%d) not supported.", type);
+        psFree(out);
+        out = NULL;
+    }
+    return out;
+}
Index: /tags/rel2_1/psLib/src/image/psImageManip.h
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageManip.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageManip.h	(revision 1553)
@@ -0,0 +1,180 @@
+
+/** @file  psImageManip.h
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Image Pixel Manipulations" and
+ *         "Image Geometry Manipulations".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:05:53 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGE_MANIP_H
+#define PS_IMAGE_MANIP_H
+
+#include "psImage.h"
+
+/// @addtogroup Image
+/// @{
+
+/** Clip image values outside of range to given values
+ *
+ *  All pixels with values less than min are set to the value vmin.  all pixels
+ *  with values greater than max are set to the value vmax. This function is
+ *  defined for psU8, psU16, psS8, psS16, psF32, psF64, psC32, and psC64.
+ *
+ *  @return int     The number of clipped pixels
+ */
+int psImageClip(
+    psImage* input,                    ///< the image to clip
+    psF64 min,                         ///< the minimum image value allowed
+    psF64 vmin,                        ///< the value pixels < min are set to
+    psF64 max,                         ///< the maximum image value allowed
+    psF64 vmax                         ///< the value pixels > max are set to
+);
+
+/** Clip image values outside of a specified complex region
+ *
+ *  All pixels outside of the rectangular region in complex space formed by
+ *  the min and max input parameters are set to the value vmax (if either
+ *  the real or imaginary portion exceeds the respective max values), or vmin. 
+ *  This function is defined for psC32, and psC64 imagery only.
+ *
+ *  @return int     The number of clipped pixels
+ */
+int psImageClipComplexRegion(
+    psImage* input,                    ///< the image to clip
+    psC64 min,                         ///< the minimum image value allowed
+    psC64 vmin,                        ///< the value pixels < min are set to
+    psC64 max,                         ///< the maximum image value allowed
+    psC64 vmax                         ///< the value pixels > max are set to
+);
+
+/** Clip NaN image pixels to given value.
+ *
+ *  Pixels with NaN, +Inf, or -Inf values are set to the specified value. This
+ *  function is defined for psF32, psF64, psC32, and psC64.
+ *
+ *  @return int     The number of clipped pixels
+ */
+int psImageClipNaN(
+    psImage* input,                    ///< the image to clip
+    psF64 value                        ///< the value to set all NaN/Inf values to
+);
+
+/** Overlay subregion of image with another image
+ *
+ *  Replace the pixels in the image which correspond to the pixels in OVERLAY
+ *  with values derived from the IMAGE and OVERLAY based on the given operator
+ *  OP.  Valid operators are "=" (set image value to OVERLAY value), "+" (add
+ *  OVERLAY value to image value), "-" (subtract OVERLAY from image), "*"
+ *  (multiply OVERLAY times image), "/" (divide image by OVERLAY).  This
+ *  function is defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
+ *
+ *  @return int         0 if success, non-zero if failed.
+ */
+int psImageOverlaySection(
+    psImage* image,                    ///< target image
+    const psImage* overlay,            ///< the overlay image
+    int col0,                          ///< the column to start overlay
+    int row0,                          ///< the row to start overlay
+    const char *op                     ///< the operation to perform for overlay
+);
+
+/** Rebin image to new scale.
+ *
+ *  A new image is constructed in which the dimensions are reduced by a factor of
+ *  1/scale.  The scale, always a positive number, is equal in each dimension and
+ *  specified the number of pixels used to define a new pixel in the output image.
+ *  The output image is generated from all input image pixels. This function is 
+ *  defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
+ *
+ *  @return psImage    new image formed by rebinning input image.
+ */
+psImage* psImageRebin(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    unsigned int scale,                ///< the scale to rebin for each dimension
+    const psStats* stats
+    ///< the statistic to perform when rebinning.  Only one method should be set.
+);
+
+/** Resample image to new scale.
+ *
+ *  A new image is constructed in which the dimensions are increased by a 
+ *  factor of scale. The scale, always a positive number, is equal in each 
+ *  dimension. The output image is generated from all input image pixels. 
+ *  Each pixel in the output image is derived by interpolating between 
+ *  neighboring pixels using the specified interpolation method (mode).
+ *
+ *  @return psImage*    resampled image result
+ */
+psImage* psImageResample(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    int scale,                         ///< resample scaling factor
+    psImageInterpolateMode mode        ///< the interpolation mode used in resampling
+);
+
+/** Rotate the input image by given angle, specified in degrees.
+ *
+ *  The output image must contain all of the pixels from the input image in 
+ *  their new frame. Pixels in the output image which do not map to input 
+ *  pixels should be set to exposed. The center of rotation is always the 
+ *  center pixel of the image. The rotation is specified in the sense that a 
+ *  positive angle is an anti-clockwise rotation. This function must be 
+ *  defined for the following types: psU8, psU16, psS8, psS16, psF32, psF64, 
+ *  psC32, psC64.
+ *
+ *  @return psImage*     the rotated image result.
+ */
+psImage* psImageRotate(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    float angle,                       ///< the rotation angle in degrees.
+    float unexposedValue,              ///< the output image pixel values for non-imagery areas
+    psImageInterpolateMode mode        ///< the interpolation mode used
+);
+
+/** Shift image by an arbitrary number of pixels (dx,dy) in either direction.
+ *
+ *  If the shift values are fractional, the output pixel values should 
+ *  interpolate between the input pixel values. The output image has the same 
+ *  dimensions as the input image. Pixels which fall off the edge of the 
+ *  output image are lost. Newly exposed pixels are set to the value given by 
+ *  exposed. This function must be defined for the following types: psU8, 
+ *  psU16, psS8, psS16, psF32, psF64, psC32, psC64.
+ *
+ *  @return psImage*     the shifted image result.
+ */
+psImage* psImageShift(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    float dx,                          ///< the shift in x direction.
+    float dy,                          ///< the shift in y direction.
+    float unexposedValue,              ///< the output image pixel values for non-imagery areas
+    psImageInterpolateMode mode        ///< the interpolation mode to use
+);
+
+/** Roll image by an integer number of pixels in either direction.
+ * 
+ *  The output image is the same dimensions as the input image.  Edge pixels
+ *  wrap to the other side (no values are lost).  This function is 
+ *  defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
+ *
+ *  @return psImage* the rolled version of the input image.
+ */
+psImage* psImageRoll(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    int dx,                            ///< number of pixels to roll in the x-dimension
+    int dy                             ///< number of pixels to roll in the y-dimension
+);
+
+#endif
Index: /tags/rel2_1/psLib/src/image/psImageStats.c
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageStats.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageStats.c	(revision 1553)
@@ -0,0 +1,404 @@
+
+/** @file psImageStats.c
+*  \brief Routines for calculating statistics on images.
+*  @ingroup ImageStats
+*
+*  This file will hold the prototypes for procedures which calculate
+*  statistic on images, histograms on images, and fit/evaluate Chebyshev
+*  polynomials to images.
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psStats.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psImageStats.h"
+
+/// This routine must determine the various statistics for the image.
+
+/*****************************************************************************
+    NOTE: verify that image/mask have the correct types, and sizes.
+ *****************************************************************************/
+psStats* psImageStats(psStats* stats, psImage* in, psImage* mask, int maskVal)
+{
+    psVector* junkData = NULL;
+    psVector* junkMask = NULL;
+
+    if (stats == NULL) {
+        psError(__func__, "The input psStats struct can not be NULL.");
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "The input image can not be NULL.");
+        return NULL;
+    }
+
+    if (stats->options == 0) {
+        psError(__func__, "No statistic option/operation was specified.");
+        return stats;
+    }
+    // stuff the image data into a psVector
+    // struct.
+    junkData = psAlloc(sizeof(psVector));
+    junkData->type = in->type;
+    junkData->nalloc = in->numRows * in->numCols;
+    junkData->n = junkData->nalloc;
+    junkData->data.V = in->data.V[0];      // since
+    // psImage
+    // data
+    // is
+    // contiguous...
+
+    if (mask != NULL) {
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
+            psFree(junkData);
+            return NULL;
+        }
+        // stuff the mask data into a psVector
+        // struct.
+        junkMask = psAlloc(sizeof(psVector));
+        junkMask->type = mask->type;
+        junkMask->nalloc = mask->numRows * mask->numCols;
+        junkMask->n = junkMask->nalloc;
+        junkMask->data.V = mask->data.V[0];
+    }
+
+    stats = psVectorStats(stats, junkData, junkMask, maskVal);
+
+    psFree(junkMask);
+    psFree(junkData);
+    return (stats);
+}
+
+/*****************************************************************************
+    NOTE: We assume that the psHistogram structure out has already been
+    allocated and initialized.
+    NOTE: verify that image/mask have the, correct types and  sizes.
+ *****************************************************************************/
+psHistogram* psImageHistogram(psHistogram* out, psImage* in, psImage* mask, unsigned int maskVal)
+{
+    psVector* junkData = NULL;
+    psVector* junkMask = NULL;
+
+    // NOTE: Verify this action.
+    if ((out == NULL) || (in == NULL)) {
+        return (NULL);
+    }
+
+    junkData = psAlloc(sizeof(psVector));
+    junkData->type = in->type;
+    junkData->nalloc = in->numRows * in->numCols;
+    junkData->n = junkData->nalloc;
+    junkData->data.V = in->data.V[0];      // since
+    // psImage
+    // data
+    // is
+    // contiguous...
+
+    if (mask != NULL) {
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
+            psFree(junkData);
+            return NULL;
+        }
+        // stuff the mask data into a psVector
+        // struct.
+        junkMask = psAlloc(sizeof(psVector));
+        junkMask->type = mask->type;
+        junkMask->nalloc = mask->numRows * mask->numCols;
+        junkMask->n = junkMask->nalloc;
+        junkMask->data.V = mask->data.V[0];
+    }
+
+    out = psVectorHistogram(out, junkData, junkMask, maskVal);
+
+    psFree(junkMask);
+    psFree(junkData);
+
+    return (out);
+}
+
+float *p_psCalcScaleFactorsFit(int n)
+{
+    int i = 0;
+    float tmp = 0.0;
+    float *scalingFactors = (float *)psAlloc(n * sizeof(float));
+
+    for (i = 0; i < n; i++) {
+        // ((2.0 * (float) i) / ((float) (n-1)))
+        // - 1.0;
+        // tmp = (float) (i + 1);
+        tmp = (float)(n - i);
+        tmp = (M_PI * (tmp - 0.5)) / ((float)n);
+        scalingFactors[i] = cos(tmp);
+    }
+
+    return (scalingFactors);
+}
+
+/*****************************************************************************
+p_psCalcScaleFactorsEval(n): The Chebyshev polynomials are defined over the
+interval [-1.0 : 1.0].  Images typically have sizes of 512x512 or more.  In
+order to use Chebyshev polynomials, we must scales the coordinates from
+0:512 to -1:1.  This routine takes as input an integer N and produces as
+output a vector of evenly spaced floating point values between -1.0:1.0.
+ *****************************************************************************/
+float *p_psCalcScaleFactorsEval(int n)
+{
+    int i = 0;
+    float tmp = 0.0;
+
+    return p_psCalcScaleFactorsFit(n);
+
+    printf("Should not get here\n");
+    float *scalingFactors = (float *)psAlloc(n * sizeof(float));
+
+    for (i = 0; i < n; i++) {
+        // scalingFactors[i] = ((2.0 * (float) i)
+        // / ((float) (n-1))) - 1.0;
+        tmp = (float)(n - i);
+        tmp = (M_PI * (tmp - 0.5)) / ((float)n);
+        scalingFactors[i] = cos(tmp);
+    }
+    return (scalingFactors);
+}
+
+psPolynomial1D* *p_psCreateChebyshevPolys(int maxChebyPoly)
+{
+    psPolynomial1D* *chebPolys = NULL;
+    int i = 0;
+    int j = 0;
+
+    chebPolys = (psPolynomial1D* *) psAlloc(maxChebyPoly * sizeof(psPolynomial1D* ));
+    for (i = 0; i < maxChebyPoly; i++) {
+        chebPolys[i] = psPolynomial1DAlloc(i + 1);
+    }
+
+    // Create the Chebyshev polynomials.
+    // Polynomial i has i-th order.
+    chebPolys[0]->coeff[0] = 1;
+    chebPolys[1]->coeff[1] = 1;
+    for (i = 2; i < maxChebyPoly; i++) {
+        for (j = 0; j < chebPolys[i - 1]->n; j++) {
+            chebPolys[i]->coeff[j + 1] = 2 * chebPolys[i - 1]->coeff[j];
+        }
+        for (j = 0; j < chebPolys[i - 2]->n; j++) {
+            chebPolys[i]->coeff[j] -= chebPolys[i - 2]->coeff[j];
+        }
+    }
+
+    return (chebPolys);
+}
+
+/*****************************************************************************
+psImageFitPolynomial(): This routine takes as input a 2-D image and produces
+as output the coefficients of the Chebyshev polynomials which match that
+input image.
+  Input:
+  Output:
+  Internal Data Structures:
+    chebPolys[i][j] 
+    sums[i][j]: This will contain the sum of 
+                input->data.F32[x][y] *
+                psPolynomial1DEval((float) x, chebPolys[i]) *
+                psPolynomial1DEval((float) y, chebPolys[j]);
+        over all pixels (x,y) in the image.
+ *****************************************************************************/
+psPolynomial2D* psImageFitPolynomial(const psImage* input, psPolynomial2D* coeffs)
+{
+    int x = 0;
+    int y = 0;
+    int i = 0;
+    int j = 0;
+    float **sums = NULL;
+    psPolynomial1D* *chebPolys = NULL;
+    int maxChebyPoly = 0;
+    float *cScalingFactors = NULL;
+    float *rScalingFactors = NULL;
+    float tmp = 0.0;
+
+    // Create the sums[][] data structure.  This
+    // will hold the LHS of
+    // equation
+    // 29 in the ADD: sums[k][l] = SUM {
+    // image(x,y) * Tk(x) * Tl(y) }
+    sums = (float **)psAlloc(coeffs->nX * sizeof(float *));
+    for (i = 0; i < coeffs->nX; i++) {
+        sums[i] = (float *)psAlloc(coeffs->nY * sizeof(float));
+    }
+
+    // We scale the pixel positions to values
+    // between -1.0 and 1.0
+    rScalingFactors = p_psCalcScaleFactorsFit(input->numRows);
+    cScalingFactors = p_psCalcScaleFactorsFit(input->numCols);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly);
+
+    // Sanity check for the Chebyshevs.
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            tmp = 0.0;
+            for (x = 0; x < input->numRows; x++) {
+                tmp +=
+                    psPolynomial1DEval
+                    (rScalingFactors[x], chebPolys[i]) * psPolynomial1DEval(rScalingFactors[x], chebPolys[j]);
+
+            }
+            // printf("SUM(Cheby(%d) * Cheby(%d))
+            // is %f\n", i, j, tmp);
+        }
+    }
+
+    // Compute the sums[][] data structure.
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            sums[i][j] = 0.0;
+            for (x = 0; x < input->numRows; x++) {
+                for (y = 0; y < input->numCols; y++) {
+                    sums[i][j] +=
+                        input->data.F32[x][y] *
+                        psPolynomial1DEval
+                        (rScalingFactors[x],
+                         chebPolys[i]) * psPolynomial1DEval(cScalingFactors[y], chebPolys[j]);
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            coeffs->coeff[i][j] = sums[i][j];
+            coeffs->coeff[i][j] /= (float)(input->numRows * input->numCols);
+
+            if ((i != 0) && (j != 0)) {
+                coeffs->coeff[i][j] *= 4.0;
+            } else if ((i == 0) && (j == 0)) {
+                coeffs->coeff[i][j] *= 1.0;
+            } else {
+                coeffs->coeff[i][j] *= 2.0;
+            }
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    for (i = 0; i < maxChebyPoly; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    // Free some data
+    for (i = 0; i < coeffs->nX; i++) {
+        psFree(sums[i]);
+    }
+    psFree(sums);
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return (coeffs);
+}
+
+/*****************************************************************************
+ 
+ *****************************************************************************/
+psImage* psImageEvalPolynomial(psImage* input, const psPolynomial2D* coeffs)
+{
+    int x = 0;
+    int y = 0;
+    int i = 0;
+    int j = 0;
+    float **sums = NULL;
+    psPolynomial1D* *chebPolys = NULL;
+    int maxChebyPoly = 0;
+    float *cScalingFactors = NULL;
+    float *rScalingFactors = NULL;
+    float polySum = 0.0;
+
+    // Create the sums[][] data structure.  This
+    // will hold the LHS of
+    // equation
+    // 29 in the ADD: sums[k][l] = SUM {
+    // image(x,y) * Tk(x) * Tl(y) }
+    sums = (float **)psAlloc(coeffs->nX * sizeof(float *));
+    for (i = 0; i < coeffs->nX; i++) {
+        sums[i] = (float *)psAlloc(coeffs->nY * sizeof(float));
+    }
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            sums[i][j] = 0.0;
+        }
+    }
+
+    // We scale the pixel positions to values
+    // between -1.0 and 1.0
+    rScalingFactors = p_psCalcScaleFactorsEval(input->numRows);
+    cScalingFactors = p_psCalcScaleFactorsEval(input->numCols);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly);
+
+    for (x = 0; x < input->numRows; x++) {
+        for (y = 0; y < input->numCols; y++) {
+            polySum = 0.0;
+            for (i = 0; i < coeffs->nX; i++) {
+                for (j = 0; j < coeffs->nY; j++) {
+                    polySum +=
+                        psPolynomial1DEval
+                        (rScalingFactors[x],
+                         chebPolys[i]) *
+                        psPolynomial1DEval(cScalingFactors[y], chebPolys[j]) * coeffs->coeff[i][j];
+
+                }
+            }
+            input->data.F32[x][y] = polySum;
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    for (i = 0; i < maxChebyPoly; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    // Free some data
+    for (i = 0; i < coeffs->nX; i++) {
+        psFree(sums[i]);
+    }
+    psFree(sums);
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return input;
+}
Index: /tags/rel2_1/psLib/src/image/psImageStats.h
===================================================================
--- /tags/rel2_1/psLib/src/image/psImageStats.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/image/psImageStats.h	(revision 1553)
@@ -0,0 +1,89 @@
+/** @file psImageStats.h
+*  \brief Routines for calculating statistics on images.
+*  @ingroup ImageStats
+*
+*  This file will hold the prototypes for procedures which calculate
+*  statistic on images, histograms on images, and fit/evaluate Chebyshev
+*  polynomials to images.
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#if !defined(PS_IMAGE_STATS_H)
+#define PS_IMAGE_STATS_H
+
+#include "psType.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psFunctions.h"
+
+/// @addtogroup ImageStats
+/// @{
+
+/** This routine must determine the various statistics for the image.
+ *
+ *  Determine statistics for image (or subimage). The statistics to be 
+ *  determined are specified by stats. The mask allows pixels to be excluded 
+ *  if their corresponding mask pixel value matches the value of maskVal. 
+ *  This function must be defined for the following types: psS8, psU16, psF32, 
+ *  psF64.
+ *
+ *  @return psStats*    the resulting statistics result(s)
+ */
+psStats* psImageStats(
+    psStats* stats,                    ///< defines statistics to be calculated
+    psImage* in,                       ///< image (or subimage) to calculate stats
+    psImage* mask,                     ///< mask data for image (NULL ok)
+    int maskVal                        ///< mask Mask for mask
+);
+
+/** Construct a histogram from an image (or subimage).
+ *
+ *  The histogram to generate is specified by psHistogram hist (see section 
+ *  4.3.2 in SDRS). This function must be defined for the following types: 
+ *  psS8, psU16, psF32, psF64.
+ *
+ *  @return psHistogram*     the resulting histogram
+ */
+psHistogram* psImageHistogram(
+    psHistogram* out,                  ///< input histogram description & target
+    psImage* in,                       ///< Image data to be histogramed.
+    psImage* mask,                     ///< mask data for image (NULL ok)
+    unsigned int maskVal               ///< mask Mask for mask
+);
+
+/** Fit a 2-D polynomial surface to an image.
+ *
+ *  The input structure coeffs contains the desired order and terms of 
+ *  interest. This function must be defined for the following types: psS8, 
+ *  psU16, psF32, psF64.
+ *
+ *  @return psPolynomial2D*     fitted polynomial result
+ *
+ */
+psPolynomial2D* psImageFitPolynomial(
+    const psImage* input,              ///< image to fit
+    psPolynomial2D* coeffs             ///< coefficient structure carries in desired terms & target
+);
+
+/** Evaluate a 2-D polynomial surface for the image pixels.
+ *
+ *  Given the input polynomial coefficients, set the image pixel values on the 
+ *  basis of the polynomial function. This function must be defined for the 
+ *  following types: psS8, psU16, psF32, psF64.
+ *
+ *  @return psImage*    the resulting image
+ */
+psImage* psImageEvalPolynomial(
+    psImage* input,                    ///< input image
+    const psPolynomial2D* coeffs       ///< coefficient structure carries in desired terms
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/imageops/psImageStats.c
===================================================================
--- /tags/rel2_1/psLib/src/imageops/psImageStats.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/imageops/psImageStats.c	(revision 1553)
@@ -0,0 +1,404 @@
+
+/** @file psImageStats.c
+*  \brief Routines for calculating statistics on images.
+*  @ingroup ImageStats
+*
+*  This file will hold the prototypes for procedures which calculate
+*  statistic on images, histograms on images, and fit/evaluate Chebyshev
+*  polynomials to images.
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psStats.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psImageStats.h"
+
+/// This routine must determine the various statistics for the image.
+
+/*****************************************************************************
+    NOTE: verify that image/mask have the correct types, and sizes.
+ *****************************************************************************/
+psStats* psImageStats(psStats* stats, psImage* in, psImage* mask, int maskVal)
+{
+    psVector* junkData = NULL;
+    psVector* junkMask = NULL;
+
+    if (stats == NULL) {
+        psError(__func__, "The input psStats struct can not be NULL.");
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "The input image can not be NULL.");
+        return NULL;
+    }
+
+    if (stats->options == 0) {
+        psError(__func__, "No statistic option/operation was specified.");
+        return stats;
+    }
+    // stuff the image data into a psVector
+    // struct.
+    junkData = psAlloc(sizeof(psVector));
+    junkData->type = in->type;
+    junkData->nalloc = in->numRows * in->numCols;
+    junkData->n = junkData->nalloc;
+    junkData->data.V = in->data.V[0];      // since
+    // psImage
+    // data
+    // is
+    // contiguous...
+
+    if (mask != NULL) {
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
+            psFree(junkData);
+            return NULL;
+        }
+        // stuff the mask data into a psVector
+        // struct.
+        junkMask = psAlloc(sizeof(psVector));
+        junkMask->type = mask->type;
+        junkMask->nalloc = mask->numRows * mask->numCols;
+        junkMask->n = junkMask->nalloc;
+        junkMask->data.V = mask->data.V[0];
+    }
+
+    stats = psVectorStats(stats, junkData, junkMask, maskVal);
+
+    psFree(junkMask);
+    psFree(junkData);
+    return (stats);
+}
+
+/*****************************************************************************
+    NOTE: We assume that the psHistogram structure out has already been
+    allocated and initialized.
+    NOTE: verify that image/mask have the, correct types and  sizes.
+ *****************************************************************************/
+psHistogram* psImageHistogram(psHistogram* out, psImage* in, psImage* mask, unsigned int maskVal)
+{
+    psVector* junkData = NULL;
+    psVector* junkMask = NULL;
+
+    // NOTE: Verify this action.
+    if ((out == NULL) || (in == NULL)) {
+        return (NULL);
+    }
+
+    junkData = psAlloc(sizeof(psVector));
+    junkData->type = in->type;
+    junkData->nalloc = in->numRows * in->numCols;
+    junkData->n = junkData->nalloc;
+    junkData->data.V = in->data.V[0];      // since
+    // psImage
+    // data
+    // is
+    // contiguous...
+
+    if (mask != NULL) {
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
+            psFree(junkData);
+            return NULL;
+        }
+        // stuff the mask data into a psVector
+        // struct.
+        junkMask = psAlloc(sizeof(psVector));
+        junkMask->type = mask->type;
+        junkMask->nalloc = mask->numRows * mask->numCols;
+        junkMask->n = junkMask->nalloc;
+        junkMask->data.V = mask->data.V[0];
+    }
+
+    out = psVectorHistogram(out, junkData, junkMask, maskVal);
+
+    psFree(junkMask);
+    psFree(junkData);
+
+    return (out);
+}
+
+float *p_psCalcScaleFactorsFit(int n)
+{
+    int i = 0;
+    float tmp = 0.0;
+    float *scalingFactors = (float *)psAlloc(n * sizeof(float));
+
+    for (i = 0; i < n; i++) {
+        // ((2.0 * (float) i) / ((float) (n-1)))
+        // - 1.0;
+        // tmp = (float) (i + 1);
+        tmp = (float)(n - i);
+        tmp = (M_PI * (tmp - 0.5)) / ((float)n);
+        scalingFactors[i] = cos(tmp);
+    }
+
+    return (scalingFactors);
+}
+
+/*****************************************************************************
+p_psCalcScaleFactorsEval(n): The Chebyshev polynomials are defined over the
+interval [-1.0 : 1.0].  Images typically have sizes of 512x512 or more.  In
+order to use Chebyshev polynomials, we must scales the coordinates from
+0:512 to -1:1.  This routine takes as input an integer N and produces as
+output a vector of evenly spaced floating point values between -1.0:1.0.
+ *****************************************************************************/
+float *p_psCalcScaleFactorsEval(int n)
+{
+    int i = 0;
+    float tmp = 0.0;
+
+    return p_psCalcScaleFactorsFit(n);
+
+    printf("Should not get here\n");
+    float *scalingFactors = (float *)psAlloc(n * sizeof(float));
+
+    for (i = 0; i < n; i++) {
+        // scalingFactors[i] = ((2.0 * (float) i)
+        // / ((float) (n-1))) - 1.0;
+        tmp = (float)(n - i);
+        tmp = (M_PI * (tmp - 0.5)) / ((float)n);
+        scalingFactors[i] = cos(tmp);
+    }
+    return (scalingFactors);
+}
+
+psPolynomial1D* *p_psCreateChebyshevPolys(int maxChebyPoly)
+{
+    psPolynomial1D* *chebPolys = NULL;
+    int i = 0;
+    int j = 0;
+
+    chebPolys = (psPolynomial1D* *) psAlloc(maxChebyPoly * sizeof(psPolynomial1D* ));
+    for (i = 0; i < maxChebyPoly; i++) {
+        chebPolys[i] = psPolynomial1DAlloc(i + 1);
+    }
+
+    // Create the Chebyshev polynomials.
+    // Polynomial i has i-th order.
+    chebPolys[0]->coeff[0] = 1;
+    chebPolys[1]->coeff[1] = 1;
+    for (i = 2; i < maxChebyPoly; i++) {
+        for (j = 0; j < chebPolys[i - 1]->n; j++) {
+            chebPolys[i]->coeff[j + 1] = 2 * chebPolys[i - 1]->coeff[j];
+        }
+        for (j = 0; j < chebPolys[i - 2]->n; j++) {
+            chebPolys[i]->coeff[j] -= chebPolys[i - 2]->coeff[j];
+        }
+    }
+
+    return (chebPolys);
+}
+
+/*****************************************************************************
+psImageFitPolynomial(): This routine takes as input a 2-D image and produces
+as output the coefficients of the Chebyshev polynomials which match that
+input image.
+  Input:
+  Output:
+  Internal Data Structures:
+    chebPolys[i][j] 
+    sums[i][j]: This will contain the sum of 
+                input->data.F32[x][y] *
+                psPolynomial1DEval((float) x, chebPolys[i]) *
+                psPolynomial1DEval((float) y, chebPolys[j]);
+        over all pixels (x,y) in the image.
+ *****************************************************************************/
+psPolynomial2D* psImageFitPolynomial(const psImage* input, psPolynomial2D* coeffs)
+{
+    int x = 0;
+    int y = 0;
+    int i = 0;
+    int j = 0;
+    float **sums = NULL;
+    psPolynomial1D* *chebPolys = NULL;
+    int maxChebyPoly = 0;
+    float *cScalingFactors = NULL;
+    float *rScalingFactors = NULL;
+    float tmp = 0.0;
+
+    // Create the sums[][] data structure.  This
+    // will hold the LHS of
+    // equation
+    // 29 in the ADD: sums[k][l] = SUM {
+    // image(x,y) * Tk(x) * Tl(y) }
+    sums = (float **)psAlloc(coeffs->nX * sizeof(float *));
+    for (i = 0; i < coeffs->nX; i++) {
+        sums[i] = (float *)psAlloc(coeffs->nY * sizeof(float));
+    }
+
+    // We scale the pixel positions to values
+    // between -1.0 and 1.0
+    rScalingFactors = p_psCalcScaleFactorsFit(input->numRows);
+    cScalingFactors = p_psCalcScaleFactorsFit(input->numCols);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly);
+
+    // Sanity check for the Chebyshevs.
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            tmp = 0.0;
+            for (x = 0; x < input->numRows; x++) {
+                tmp +=
+                    psPolynomial1DEval
+                    (rScalingFactors[x], chebPolys[i]) * psPolynomial1DEval(rScalingFactors[x], chebPolys[j]);
+
+            }
+            // printf("SUM(Cheby(%d) * Cheby(%d))
+            // is %f\n", i, j, tmp);
+        }
+    }
+
+    // Compute the sums[][] data structure.
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            sums[i][j] = 0.0;
+            for (x = 0; x < input->numRows; x++) {
+                for (y = 0; y < input->numCols; y++) {
+                    sums[i][j] +=
+                        input->data.F32[x][y] *
+                        psPolynomial1DEval
+                        (rScalingFactors[x],
+                         chebPolys[i]) * psPolynomial1DEval(cScalingFactors[y], chebPolys[j]);
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            coeffs->coeff[i][j] = sums[i][j];
+            coeffs->coeff[i][j] /= (float)(input->numRows * input->numCols);
+
+            if ((i != 0) && (j != 0)) {
+                coeffs->coeff[i][j] *= 4.0;
+            } else if ((i == 0) && (j == 0)) {
+                coeffs->coeff[i][j] *= 1.0;
+            } else {
+                coeffs->coeff[i][j] *= 2.0;
+            }
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    for (i = 0; i < maxChebyPoly; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    // Free some data
+    for (i = 0; i < coeffs->nX; i++) {
+        psFree(sums[i]);
+    }
+    psFree(sums);
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return (coeffs);
+}
+
+/*****************************************************************************
+ 
+ *****************************************************************************/
+psImage* psImageEvalPolynomial(psImage* input, const psPolynomial2D* coeffs)
+{
+    int x = 0;
+    int y = 0;
+    int i = 0;
+    int j = 0;
+    float **sums = NULL;
+    psPolynomial1D* *chebPolys = NULL;
+    int maxChebyPoly = 0;
+    float *cScalingFactors = NULL;
+    float *rScalingFactors = NULL;
+    float polySum = 0.0;
+
+    // Create the sums[][] data structure.  This
+    // will hold the LHS of
+    // equation
+    // 29 in the ADD: sums[k][l] = SUM {
+    // image(x,y) * Tk(x) * Tl(y) }
+    sums = (float **)psAlloc(coeffs->nX * sizeof(float *));
+    for (i = 0; i < coeffs->nX; i++) {
+        sums[i] = (float *)psAlloc(coeffs->nY * sizeof(float));
+    }
+    for (i = 0; i < coeffs->nX; i++) {
+        for (j = 0; j < coeffs->nY; j++) {
+            sums[i][j] = 0.0;
+        }
+    }
+
+    // We scale the pixel positions to values
+    // between -1.0 and 1.0
+    rScalingFactors = p_psCalcScaleFactorsEval(input->numRows);
+    cScalingFactors = p_psCalcScaleFactorsEval(input->numCols);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly);
+
+    for (x = 0; x < input->numRows; x++) {
+        for (y = 0; y < input->numCols; y++) {
+            polySum = 0.0;
+            for (i = 0; i < coeffs->nX; i++) {
+                for (j = 0; j < coeffs->nY; j++) {
+                    polySum +=
+                        psPolynomial1DEval
+                        (rScalingFactors[x],
+                         chebPolys[i]) *
+                        psPolynomial1DEval(cScalingFactors[y], chebPolys[j]) * coeffs->coeff[i][j];
+
+                }
+            }
+            input->data.F32[x][y] = polySum;
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    for (i = 0; i < maxChebyPoly; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    // Free some data
+    for (i = 0; i < coeffs->nX; i++) {
+        psFree(sums[i]);
+    }
+    psFree(sums);
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return input;
+}
Index: /tags/rel2_1/psLib/src/imageops/psImageStats.h
===================================================================
--- /tags/rel2_1/psLib/src/imageops/psImageStats.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/imageops/psImageStats.h	(revision 1553)
@@ -0,0 +1,89 @@
+/** @file psImageStats.h
+*  \brief Routines for calculating statistics on images.
+*  @ingroup ImageStats
+*
+*  This file will hold the prototypes for procedures which calculate
+*  statistic on images, histograms on images, and fit/evaluate Chebyshev
+*  polynomials to images.
+*
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#if !defined(PS_IMAGE_STATS_H)
+#define PS_IMAGE_STATS_H
+
+#include "psType.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psFunctions.h"
+
+/// @addtogroup ImageStats
+/// @{
+
+/** This routine must determine the various statistics for the image.
+ *
+ *  Determine statistics for image (or subimage). The statistics to be 
+ *  determined are specified by stats. The mask allows pixels to be excluded 
+ *  if their corresponding mask pixel value matches the value of maskVal. 
+ *  This function must be defined for the following types: psS8, psU16, psF32, 
+ *  psF64.
+ *
+ *  @return psStats*    the resulting statistics result(s)
+ */
+psStats* psImageStats(
+    psStats* stats,                    ///< defines statistics to be calculated
+    psImage* in,                       ///< image (or subimage) to calculate stats
+    psImage* mask,                     ///< mask data for image (NULL ok)
+    int maskVal                        ///< mask Mask for mask
+);
+
+/** Construct a histogram from an image (or subimage).
+ *
+ *  The histogram to generate is specified by psHistogram hist (see section 
+ *  4.3.2 in SDRS). This function must be defined for the following types: 
+ *  psS8, psU16, psF32, psF64.
+ *
+ *  @return psHistogram*     the resulting histogram
+ */
+psHistogram* psImageHistogram(
+    psHistogram* out,                  ///< input histogram description & target
+    psImage* in,                       ///< Image data to be histogramed.
+    psImage* mask,                     ///< mask data for image (NULL ok)
+    unsigned int maskVal               ///< mask Mask for mask
+);
+
+/** Fit a 2-D polynomial surface to an image.
+ *
+ *  The input structure coeffs contains the desired order and terms of 
+ *  interest. This function must be defined for the following types: psS8, 
+ *  psU16, psF32, psF64.
+ *
+ *  @return psPolynomial2D*     fitted polynomial result
+ *
+ */
+psPolynomial2D* psImageFitPolynomial(
+    const psImage* input,              ///< image to fit
+    psPolynomial2D* coeffs             ///< coefficient structure carries in desired terms & target
+);
+
+/** Evaluate a 2-D polynomial surface for the image pixels.
+ *
+ *  Given the input polynomial coefficients, set the image pixel values on the 
+ *  basis of the polynomial function. This function must be defined for the 
+ *  following types: psS8, psU16, psF32, psF64.
+ *
+ *  @return psImage*    the resulting image
+ */
+psImage* psImageEvalPolynomial(
+    psImage* input,                    ///< input image
+    const psPolynomial2D* coeffs       ///< coefficient structure carries in desired terms
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/mainpage.dox
===================================================================
--- /tags/rel2_1/psLib/src/mainpage.dox	(revision 1553)
+++ /tags/rel2_1/psLib/src/mainpage.dox	(revision 1553)
@@ -0,0 +1,154 @@
+/** @mainpage psLib Image Processing Library
+
+
+@section intro Introduction
+
+This library contains the Pan-STARRS Image Processing Pipeline (IPP) common library,
+psLib. The intended use is to provide a set of basic software functions in which
+can be used throughout the Pan-STARRS project to simplify programming tasks. Among
+the benefits are: 
+ - reuse of code, 
+ - simplification of testing, 
+ - streamlining of code, and 
+ - isolation of functionality that may be subject to change.     
+
+The capabilities provided by psLib are grouped into the following areas which are
+also reflected in the file system directory structure:
+ - System Utilities
+ - Data Collections
+ - Image Operations
+ - Data Manipulation
+ - Astronomy
+
+This list is sorted in hierarchical order: The later entries depend on the functions and 
+data types of the earlier entries.
+
+The installed code for psLib consists of header files and binary libraries in 
+the form of static (libpslib.a) and shared (libpslib.so or libpslib.dylib, 
+depending on operating system.) Assuming these components have been built and 
+installed in the standard library path, psLib may be used within a program by 
+including the line #include <pslib.h> and linking using the '-lpslib' option
+while linking.
+
+
+@section extinstall Required 3rd Party Libraries
+
+Before building psLib from source, several 3rd party software libraries must 
+be installed.  These include: 
+ - GNU Scientific Library (GSL)
+     - Available at http://www.gnu.org/software/gsl
+     - Compatibility tested with version is 1.4
+ - Fastest Fourier Transform in the West (FFTW), version 3
+     - Available at http://www.fftw.org
+     - Compatibility tested with version is 3.0.1
+ - C Flexible Image Transport System Input output (CFITSIO), version 2.480 or later
+     - Available at http://heasarc.gsfc.nasa.gov/docs/software/fitsio
+     - Compatibility tested with version is 2.490
+     - Versions earlier than 2.480 will not work as new functionality introduced in 2.480 is exercised
+ - Doxygen Documentation System
+     - Available at http://www.doxygen.org
+     - Compatibility tested with version 1.3.6
+     - The optional companion package, GraphViz (a.k.a., the 'dot' command), is recommended to enable header-file dependency diagrams
+ - SLALIB 
+     - We tested with the Fortran version of the library; this may cause an additional step to get things to link on untested systems/compilers, as there is no one standard for how the function-names appear in the library to C code.  The default way that psLib uses is all-lower case with a trailing '_', but one may need to add to CFLAGS in src/Makefile.Globals the following:
+         - '-DFORTRAN_UNDERSCORE_PREFIX' if a '_' needs to be prefixed to the function names,
+         - '-DFORTRAN_DOUBLE_UNDERSCORE_SUFFIX' if two the names needs two trailing '_'s., and/or
+         - '-DFORTRAN_UPPERCASE' if the names appear as uppercase.
+     - Available at http://star-www.rl.ac.uk/
+     - Compatibility tested with package version number 2.4-12
+
+We recommend using the particular versions listed as compatibility tested, as 
+that is the only versions of the external libraries tested to work well with psLib.  
+Though it is quite possible that later versions of the libraries listed will also 
+work as well, care must be taken when upgrading these libraries to verify that its
+functionality is compatible with the tested version.
+
+@section install How to Build from Source
+
+Tested versions of psLib are put into a tar file and can be downloaded from:
+
+https://mhpcc.pan-starrs.org/code/releases
+
+Though MHPCC recommends using the released packaged tar files descibed above,
+both daily development snapshots and direct CVS access is available.  The daily
+snapshots are available at
+
+https://mhpcc.pan-starrs.org/code/snapshots
+
+These snapshots represents development code as found in CVS on the day 
+specified in the filename.  This code set may not be functional, vary in
+testing, etc.  Reasonable efforts are made to ensure that the code does 
+actually compile, but given the nature of code development, even that is not 
+always the case.  Use snapshots with great caution.
+
+If one has a login account on mhpcc.pan-starrs.org, direct CVS access is  
+possible.  Example of the commands required for direct CVS retrieval are
+as follows:
+<pre>
+$ cvs -d:ext:USERNAME@mhpcc.pan-starrs.org:/data/panstarrs/cvsroot co -r RELEASEBRANCH psLib
+</pre>
+where:
+  - USERNAME is your login name on the server
+  - RELEASEBRANCH is the desired release branch, e.g. rel1, rel2, etc.
+    
+
+@section build How to Build the psLib library.
+
+The source should build using the Makefile in the psLib/src directory.  The
+recommended steps are:
+<pre>
+$ cd psLib/src
+$ make
+$ make install
+</pre>
+<i>This builds and installs files to psLib/lib and psLib/include.</i>
+
+
+@section run How to Build and Run Tests
+
+Since psLib is a library, there is no executable, per se. However, to test the 
+installation, users may execute the unit test suite.  To build the unit test
+suite, do the following:
+<pre>
+$ cd psLib/test
+$ make
+$ make install
+$ make installtests
+</pre>
+<i>This builds and installs the unit test files to the psLib/testbin directory.</i>
+
+To run the unit test suite, do the following:
+<pre>
+$ cd psLib/testbin
+$ ./FullUnitTest
+</pre>
+or to run a particular test
+<pre>
+$ ./runTest testfilename
+</pre>
+
+Note: one can also fun the FullUnitTest from anywhere within psLib/test
+without performing the above 'make installtests' command first.  To do this,
+one needs to first set the PSLIB_ROOT environment variable to the top psLib
+directory 'psLib'.  FullUnitTest will search for tests in the subdirectories
+the the execution directory, perform a build of them (via 'make'), and run them.
+This can be useful if one wants to tweak the test code and doesn't desire to
+perform an install of all the tests each time the test file is touched.
+
+
+@section doc How to Create Code Documentation
+
+Both HTML and man page documentation may be generated from the inline 
+documentation embedded in the code using the following commands:
+<pre>
+$ cd psLib/src
+$ make docs
+</pre>
+<i>This places documentation in psLib/docs.</i>
+
+Also, a prebuilt set of code documentation for both the releases and last 
+CVS snapshot can be found at:
+
+https://mhpcc.pan-starrs.org/docs/
+
+*/
Index: /tags/rel2_1/psLib/src/math/psCompare.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psCompare.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psCompare.c	(revision 1553)
@@ -0,0 +1,80 @@
+
+/** @file psCompare.c
+ *  @brief Comparison functions for sorting routines
+ *  @ingroup Compare
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psType.h"
+#include "psCompare.h"
+
+#define COMPARE_NUMERIC_PTR(TYPE) \
+int psCompare##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)a) - **((ps##TYPE**)b); \
+}
+
+#define COMPARE_NUMERIC_PTR_DESCENDING(TYPE) \
+int psCompareDescending##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)b) - **((ps##TYPE**)a); \
+}
+
+#define COMPARE_NUMERIC(TYPE) \
+int psCompare##TYPE(const void* a, const void* b) { \
+    return *((ps##TYPE*)a) - *((ps##TYPE*)b); \
+}
+
+#define COMPARE_NUMERIC_DESCENDING(TYPE) \
+int psCompare##TYPE##Descending(const void* a, const void* b) { \
+    return *((ps##TYPE*)b) - *((ps##TYPE*)a); \
+}
+
+COMPARE_NUMERIC_PTR(S8)
+COMPARE_NUMERIC_PTR(S16)
+COMPARE_NUMERIC_PTR(S32)
+COMPARE_NUMERIC_PTR(S64)
+COMPARE_NUMERIC_PTR(U8)
+COMPARE_NUMERIC_PTR(U16)
+COMPARE_NUMERIC_PTR(U32)
+COMPARE_NUMERIC_PTR(U64)
+COMPARE_NUMERIC_PTR(F32)
+COMPARE_NUMERIC_PTR(F64)
+
+COMPARE_NUMERIC_PTR_DESCENDING(S8)
+COMPARE_NUMERIC_PTR_DESCENDING(S16)
+COMPARE_NUMERIC_PTR_DESCENDING(S32)
+COMPARE_NUMERIC_PTR_DESCENDING(S64)
+COMPARE_NUMERIC_PTR_DESCENDING(U8)
+COMPARE_NUMERIC_PTR_DESCENDING(U16)
+COMPARE_NUMERIC_PTR_DESCENDING(U32)
+COMPARE_NUMERIC_PTR_DESCENDING(U64)
+COMPARE_NUMERIC_PTR_DESCENDING(F32)
+COMPARE_NUMERIC_PTR_DESCENDING(F64)
+
+COMPARE_NUMERIC(S8)
+COMPARE_NUMERIC(S16)
+COMPARE_NUMERIC(S32)
+COMPARE_NUMERIC(S64)
+COMPARE_NUMERIC(U8)
+COMPARE_NUMERIC(U16)
+COMPARE_NUMERIC(U32)
+COMPARE_NUMERIC(U64)
+COMPARE_NUMERIC(F32)
+COMPARE_NUMERIC(F64)
+
+COMPARE_NUMERIC_DESCENDING(S8)
+COMPARE_NUMERIC_DESCENDING(S16)
+COMPARE_NUMERIC_DESCENDING(S32)
+COMPARE_NUMERIC_DESCENDING(S64)
+COMPARE_NUMERIC_DESCENDING(U8)
+COMPARE_NUMERIC_DESCENDING(U16)
+COMPARE_NUMERIC_DESCENDING(U32)
+COMPARE_NUMERIC_DESCENDING(U64)
+COMPARE_NUMERIC_DESCENDING(F32)
+COMPARE_NUMERIC_DESCENDING(F64)
Index: /tags/rel2_1/psLib/src/math/psCompare.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psCompare.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psCompare.h	(revision 1553)
@@ -0,0 +1,506 @@
+#if !defined(PS_COMPARE_H)
+#define PS_COMPARE_H
+
+/** @file psCompare.h
+ *  @brief Comparison functions for sorting routines
+ *
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @ingroup Compare
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:58:11 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/** @addtogroup Compare
+*  @{
+*/
+
+/** A comparison function for sorting elements that are pointers to data,
+ *  e.g., for psList of pointers to numeric values.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+typedef int (*psComparePtrFcn) (
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** A comparison function for sorting.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+typedef int (*psCompareFcn) (
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or lessg than the second. 
+ */
+int psCompareDescendingF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively less 
+ *                   than, equal to, or greater than the second. 
+ */
+int psCompareF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if 
+ *                   the first argument is considered to be respectively greater 
+ *                   than, equal to, or less than the second. 
+ */
+int psCompareDescendingF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/math/psMatrix.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psMatrix.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psMatrix.c	(revision 1553)
@@ -0,0 +1,582 @@
+
+/** @file  psMatrix.c
+ *
+ *  @brief Provides functions for linear algebra operations on psImages and psVectors. 
+ *
+ *  Functions are provided to:
+ *      Transpose a psImage
+ *      Compute LUD
+ *      Solve LUD
+ *      Matrix inversion
+ *      Calculate determinant
+ *      Matrix addition
+ *      Matrix subtraction
+ *      Matrix multiplication
+ *      Calculate Eigenvectors
+ *      Convert matrix to vector
+ *      Convert vector to matrix
+ *
+ *  These functions treat psImages as if they were matrices, therefore there is no psMatrix.
+ *
+ *  @author Ross Harman, MHPCC
+ *   
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_linalg.h>
+#include <gsl/gsl_permutation.h>
+#include <gsl/gsl_eigen.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psMatrix.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+/** Preprocessor macro to generate error a NULL image */
+#define PS_CHECK_NULL_VECTOR(NAME, RETURN)                                                          \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to create vector based on another */
+#define PS_CHECK_ALLOC_VECTOR(NAME, SIZE, PS_TYPE)                                                  \
+if(NAME == NULL) {                                                                                  \
+    NAME = psVectorAlloc(SIZE, PS_TYPE);                                                            \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_SIZE_VECTOR(NAME, RETURN)                                                          \
+if (NAME->n < 1) {                                                                                  \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to generate error a NULL image */
+#define PS_CHECK_NULL_IMAGE(NAME, RETURN)                                                           \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to create image based on another */
+#define PS_CHECK_ALLOC_IMAGE(NAME, NCOLS, NROWS, PS_TYPE)                                           \
+if(NAME == NULL) {                                                                                  \
+    NAME = psImageAlloc(NCOLS, NROWS, PS_TYPE);                                                     \
+}
+
+/** Preprocessor macro to generate error for zero length rows or columns */
+#define PS_CHECK_SIZE_IMAGE(NAME, RETURN)                                                           \
+if (NAME->numCols < 1 || NAME->numRows < 1) {                                                       \
+    psError(__func__,"Invalid operation: %s has zero rows or columns (%dx%d).", #NAME,              \
+            NAME->numCols, NAME->numRows);                                                          \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to generate error for image dimensionality not set to PS_DIMEN_IMAGE */
+#define PS_CHECK_DIMEN_AND_TYPE(NAME, PS_DIMEN, RETURN)                                             \
+if (NAME->type.dimen != PS_DIMEN) {                                                                 \
+    psError(__func__,"Invalid operation: %s incorrect dimensionality %d.", #NAME, PS_DIMEN);        \
+    return RETURN;                                                                                  \
+} else if(NAME->type.type != PS_TYPE_F64) {                                                         \
+    psError(__func__, "Invalid operation: %s not PS_TYPE_F64.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to check that input is not equal to output */
+#define PS_CHECK_POINTERS(NAME1, NAME2, RETURN)                                                     \
+if (NAME1 == NAME2) {                                                                               \
+    psError(__func__,"Invalid operation: Pointer to %s is same as %s.", #NAME1, #NAME2);            \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to check that an image is square */
+#define PS_CHECK_SQUARE(NAME, RETURN)                                                               \
+if (NAME->numCols != NAME->numRows) {                                                               \
+    psError(__func__,"Invalid operation: %s not square array.", #NAME);                             \
+    return RETURN;                                                                                  \
+}
+
+/** Preprocessor macro to initalize a GSL matrix. */
+#define PS_GSL_MATRIX_INITIALIZE(LHS_NAME, RHS_NAME)                                                \
+LHS_NAME.size1 = numRows;                                                                           \
+LHS_NAME.size2 = numCols;                                                                           \
+LHS_NAME.tda   = numCols;                                                                           \
+LHS_NAME.data  = RHS_NAME;
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psImage* psMatrixLUD(psImage* outImage, psVector* outPerm, psImage* inImage)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix lu;
+    gsl_permutation perm;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+    PS_CHECK_ALLOC_VECTOR(outPerm, inImage->numRows, inImage->type.type);
+    PS_CHECK_NULL_VECTOR(outPerm, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(outPerm, PS_DIMEN_VECTOR, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    perm.size = numCols;
+    outPerm->n = numCols;
+    perm.data = outPerm->data.V;
+    PS_GSL_MATRIX_INITIALIZE(lu, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu.data, inImage->data.V[0], arraySize);
+
+    // Calculate LU decomposition
+    gsl_linalg_LU_decomp(&lu, &perm, &signum);
+
+    return outImage;
+}
+
+psVector* psMatrixLUSolve(psVector* outVector, const psImage* inImage, const psVector* inVector, const
+                          psVector* inPerm)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix lu;
+    gsl_permutation perm;
+    gsl_vector b;
+    gsl_vector x;
+
+    // Error checks
+    PS_CHECK_POINTERS(outVector, inVector, outVector);
+    PS_CHECK_POINTERS(inVector, inPerm, outVector);
+    PS_CHECK_POINTERS(outVector, inPerm, outVector);
+    PS_CHECK_NULL_IMAGE(inImage, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outVector);
+    PS_CHECK_SIZE_IMAGE(inImage, outVector);
+    PS_CHECK_ALLOC_VECTOR(outVector, inImage->numRows, inImage->type.type);
+    PS_CHECK_NULL_VECTOR(outVector, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_VECTOR, outVector);
+    PS_CHECK_NULL_VECTOR(inVector, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_VECTOR, outVector);
+    PS_CHECK_NULL_VECTOR(inPerm, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inPerm, PS_DIMEN_VECTOR, outVector);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(lu, inImage->data.V[0]);
+
+    outVector->n = numCols;
+
+    perm.size = inPerm->n;
+    perm.data = inPerm->data.V;
+
+    b.size = inVector->n;
+    b.stride = 1;
+    b.data = inVector->data.V;
+
+    x.size = numCols;
+    x.stride = 1;
+    x.data = outVector->data.V;
+
+    // Solve for {x} in equation: {b} = [A]{x}
+    gsl_linalg_LU_solve(&lu, &perm, &b, &x);
+
+    return outVector;
+}
+
+psImage* psMatrixInvert(psImage* outImage, const psImage* inImage, float *restrict det)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix inv;
+    gsl_matrix *lu;
+    gsl_permutation *perm = NULL;
+
+    // Error checks
+    if (det == NULL) {
+        psError(__func__, "Invalid operation: determinant argument is NULL.");
+        return outImage;
+    }
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Allocate GSL structs
+    perm = gsl_permutation_alloc(inImage->numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(inv, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu->data, inImage->data.V[0], arraySize);
+
+    // Invert data and calculate determinant
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    gsl_linalg_LU_invert(lu, perm, &inv);
+    *det = (float)gsl_linalg_LU_det(lu, signum);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+
+    return outImage;
+}
+
+float *psMatrixDeterminant(const psImage* restrict inImage)
+{
+    int signum = 0;
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    float *det = NULL;
+    gsl_matrix *lu = NULL;
+    gsl_permutation *perm = NULL;
+
+    // Error checks
+    PS_CHECK_NULL_IMAGE(inImage, NULL);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, NULL);
+    PS_CHECK_SIZE_IMAGE(inImage, NULL);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Allocate GSL structs
+    perm = gsl_permutation_alloc(numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, 0);
+
+    // Copy psImage input data into GSL matrix data to keep input data pristine
+    memcpy(lu->data, inImage->data.V[0], arraySize);
+
+    // Calculate determinant
+    det = (float *)psAlloc(sizeof(float));
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    *det = (float)gsl_linalg_LU_det(lu, signum);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+
+    return det;
+}
+
+psImage* psMatrixMultiply(psImage* outImage, psImage* inImage1, psImage* inImage2)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix m1;
+    gsl_matrix m2;
+    gsl_matrix m3;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage1, outImage, outImage);
+    PS_CHECK_POINTERS(inImage1, inImage2, outImage);
+    PS_CHECK_NULL_IMAGE(inImage1, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage1, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage1, outImage);
+    PS_CHECK_NULL_IMAGE(inImage2, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage2, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage2, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage2->numCols, inImage2->numRows, inImage2->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(inImage1, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage1->numRows;
+    numCols = inImage1->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(outImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(m1, inImage1->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(m2, inImage2->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(m3, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage1, outImage);
+    PS_CHECK_SQUARE(inImage2, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    gsl_linalg_matmult(&m1, &m2, &m3);
+
+    return outImage;
+}
+
+psImage* psMatrixTranspose(psImage* outImage, const psImage* inImage)
+{
+    int arraySize = 0;
+    int numRows = 0;
+    int numCols = 0;
+    gsl_matrix trans;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    arraySize = PSELEMTYPE_SIZEOF(inImage->type.type) * numRows * numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(trans, outImage->data.V[0]);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Copy psImage input data into psImage output data to keep input data pristine
+    memcpy(outImage->data.V[0], inImage->data.V[0], arraySize);
+
+    // Transpose data
+    gsl_matrix_transpose(&trans);
+
+    return outImage;
+}
+
+psImage* psMatrixEigenvectors(psImage* outImage, psImage* inImage)
+{
+    int numRows = 0;
+    int numCols = 0;
+    gsl_vector *eVals = NULL;
+    gsl_eigen_symmv_workspace *w = NULL;
+    gsl_matrix out;
+    gsl_matrix in;
+
+    // Error checks
+    PS_CHECK_POINTERS(inImage, outImage, outImage);
+    PS_CHECK_NULL_IMAGE(inImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(inImage, outImage);
+    PS_CHECK_ALLOC_IMAGE(outImage, inImage->numCols, inImage->numRows, inImage->type.type);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+    PS_CHECK_SIZE_IMAGE(outImage, outImage);
+
+    // Initialize data
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+
+    // Initialize GSL data
+    PS_GSL_MATRIX_INITIALIZE(in, inImage->data.V[0]);
+    PS_GSL_MATRIX_INITIALIZE(out, outImage->data.V[0]);
+
+    // Allocate GSL structs
+    eVals = gsl_vector_alloc(numRows);
+    w = gsl_eigen_symmv_alloc(numRows);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(inImage, outImage);
+    PS_CHECK_SQUARE(outImage, outImage);
+
+    // Calculate Eigenvalues and Eigenvectors...Eigenvalues not currently used
+    gsl_eigen_symmv(&in, eVals, &out, w);
+
+    // Free GSL structs
+    gsl_eigen_symmv_free(w);
+    gsl_vector_free(eVals);
+
+    return outImage;
+}
+
+psVector* psMatrixToVector(psVector* outVector, psImage* inImage)
+{
+    int size = 0;
+
+    // Error checks
+    PS_CHECK_NULL_IMAGE(inImage, outVector);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, outVector);
+    PS_CHECK_SIZE_IMAGE(inImage, outVector);
+
+    if (inImage->numRows == 1) {
+        // Create transposed row vector
+        PS_CHECK_ALLOC_VECTOR(outVector, inImage->numCols, inImage->type.type);
+        outVector->type.dimen = PS_DIMEN_TRANSV;
+    } else if (inImage->numCols == 1) {
+        // Create non-transposed column vector
+        PS_CHECK_ALLOC_VECTOR(outVector, inImage->numRows, inImage->type.type);
+    } else {
+        psError(__func__, "Image does not have dim with 1 col or 1 row: (%d x %d).", inImage->numRows,
+                inImage->numCols);
+        return outVector;
+    }
+
+    PS_CHECK_NULL_VECTOR(outVector, outVector);
+
+    // More checks
+    if (outVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_VECTOR, outVector);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numRows;
+        }
+
+        if (outVector->n != inImage->numRows) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numRows, outVector->n);
+            return outVector;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numRows;
+
+    } else if (outVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_TRANSV, outVector);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numCols;
+        }
+
+        if (outVector->n != inImage->numCols) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numCols, outVector->n);
+            return outVector;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numCols;
+    }
+
+    memcpy(outVector->data.V, inImage->data.V[0], size);
+
+    return outVector;
+}
+
+psImage* psVectorToMatrix(psImage* outImage, psVector* inVector)
+{
+    int size = 0;
+
+    // Error checks
+    PS_CHECK_NULL_VECTOR(inVector, outImage);
+
+    if (inVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_VECTOR, outImage);
+        PS_CHECK_SIZE_VECTOR(inVector, outImage);
+        PS_CHECK_ALLOC_IMAGE(outImage, 1, inVector->n, PS_TYPE_F64)
+        // More checks for PS_DIMEN_VECTOR
+        if (outImage->numCols > 1) {
+            psError(__func__, "Image has more than 1 column: numCols = %d.", outImage->numCols);
+            return outImage;
+        } else if (outImage->numRows != inVector->n) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numRows, inVector->n);
+            return outImage;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numRows;
+
+    } else if (inVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_TRANSV, outImage);
+        PS_CHECK_SIZE_VECTOR(inVector, outImage);
+        PS_CHECK_ALLOC_IMAGE(outImage, inVector->n, 1, PS_TYPE_F64)
+        // More checks for PS_DIMEN_TRANSV
+        if (outImage->numRows > 1) {
+            psError(__func__, "Image has more than 1 row: numRows = %d.", outImage->numRows);
+            return outImage;
+        } else if (outImage->numCols != inVector->n) {
+            psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numCols, inVector->n);
+            return outImage;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numCols;
+    }
+
+    PS_CHECK_NULL_IMAGE(outImage, outImage);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, outImage);
+
+    memcpy(outImage->data.V[0], inVector->data.V, size);
+
+    return outImage;
+}
Index: /tags/rel2_1/psLib/src/math/psMatrix.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psMatrix.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psMatrix.h	(revision 1553)
@@ -0,0 +1,166 @@
+
+/** @file  psMatrix.h
+ *
+ *  @brief Provides functions for linear algebra operations on psImages and psVectors. 
+ *
+ *  Functions are provided to:
+ *      Transpose a psImage
+ *      Compute LUD
+ *      Solve LUD
+ *      Matrix inversion
+ *      Calculate determinant
+ *      Matrix multiplication
+ *      Calculate Eigenvectors
+ *      Convert matrix to vector
+ *      Convert vector to matrix
+ *
+ *  These functions treat psImages as if they were matrices, therefore there is no psMatrix. These functions
+ *  operate only with the psF64 data type.
+ *
+ *  @ingroup Matrix
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 02:35:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSMATRIX_H
+#define PSMATRIX_H
+
+/// @addtogroup Matrix
+/// @{
+
+/** LU Decomposition of psImage matrix.
+ *
+ *  Performs a LU decomposition on a psImage matrix and returns the LU matrix. If the user specifies NULL for
+ *  the outImage or outPerm arguments, then they will be automatically created. The input image must 
+ *  be square. This function operates only with the psF64 data type. Input and output arguments should not be 
+ *  the same. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to LU decomposed psImage.
+ */
+psImage* psMatrixLUD(
+    psImage* outImage,                 ///< Image to return, or NULL.
+    psVector* outPerm,                 ///< Output permutation vector used by psMatrixLUSolve.
+    psImage* inImage                   ///< Image to decompose.
+);
+
+/** LU Solution of psImage matrix.
+ *
+ *  Solves for and returns the psVector, {x} in the equation [A]{x} = {b}. If the user specifies NULL as the 
+ *  outVector argument, then it will automatically be created. The input image must be square. This function 
+ *  operates only with the psF64 data type. Input and output arguments should not be the same. GSL indexes 
+ *  the top row as the zero row, not the bottom.  
+ *
+ *  @return  psVector* : Pointer to psVector solution of matrix equation.
+ */
+psVector* psMatrixLUSolve(
+    psVector* outVector,               ///< Vector to return, or NULL.
+    const psImage* luImage,            ///< LU-decomposed matrix.
+    const psVector* inVector,          ///< Vector right-hand-side of equation.
+    const psVector* inPerm             ///< Permutation vector resulting from psMatrixLUD function.
+);
+
+/** Invert psImage matrix.
+ *
+ *  Inverts a psImage matrix and returns the determinant as an option through the argument list. If the user
+ *  specifies NULL as the outImage argument, then it will automatically be created. The input image must be 
+ *  square. This function operates only with the psF64 data type. Input and output arguments should not be 
+ *  the same. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to inverted psImage.
+ */
+psImage* psMatrixInvert(
+    psImage* outImage,                 ///< Image to return, or NULL for in-place substitution.
+    const psImage* inImage,            ///< Image to be inverted
+    float *restrict det                ///< Determinant to return, or NULL
+);
+
+/** Calculate psImage matrix determinant.
+ *
+ *  Calculates the determinant of a psImage matrix and returns the single precision floating point result. The
+ *  input image must be square. This function operates only with the psF64 data type. GSL indexes the top row 
+ *  as the zero row, not the bottom.  
+ *
+ *  @return  float: Determinant from psImage.
+ */
+float *psMatrixDeterminant(
+    const psImage* restrict inMatrix   ///< Image used to calculate determinant.
+);
+
+/** Performs psImage matrix multiplication.
+ *
+ *  Performs a classical matrix multiplication involving row and column operations. Input images must be square 
+ *  and the same size. If the user specifies NULL as the outImage argument, then it will automatically be 
+ *  created. This function operates only with the psF64 data type. GSL indexes the top row as the
+ *  zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to resulting psImage.
+ */
+psImage* psMatrixMultiply(
+    psImage* outImage,                 ///< Matrix to return, or NULL.
+    psImage* inImage1,                 ///< First input image.
+    psImage* inImage2                  ///< Second input image.
+);
+
+/** Transpose matrix.
+ *
+ *  Performs psImage matrix transpose by substituting existing rows for columns. The input image must be 
+ *  square. If the user specifies NULL as the outImage argument, then it will automaticallty be created.
+ *  This function operates only with the psF64 data type. GSL indexes the top row as the zero 
+ *  row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to transposed psImage.
+ */
+psImage* psMatrixTranspose(
+    psImage* outImage,                 ///< Image to return, or NULL
+    const psImage* inImage             ///< Image to transpose
+);
+
+/** Calculate matrix eigenvectors.
+ *
+ *  Calculates the eigenvectors for a matrix. The input image must be symmetric and square. If the user 
+ *  specifies NULL as the outImage argument, then it will automatically be created. This function operates 
+ *  only with the psF64 data type. GSL indexes the top row as the zero row, not the bottom.  
+ *
+ *  @return  psImage* : Pointer to matrix of Eigenvectors.
+ */
+psImage* psMatrixEigenvectors(
+    psImage* outImage,                 ///< Eigenvectors to return, or NULL.
+    psImage* inImage                   ///< Input image.
+);
+
+/** Convert matrix to vector.
+ *
+ *  Converts a 1-d psImage matrix into a vector. If the user specifies NULL as the outVector argument, then it
+ *  will automatically be created based on the input image (PS_DIMEN_VECTOR for an input image with 1 col or
+ *  PS_DIMENT_TRANSV for an input image with 1 row). Either the number of rows or the number of colums of the
+ *  input matrix must be 1. This function operates only  with the psF64 data type.
+ *
+ *  @return  psVector* : Pointer to psVector.
+ */
+psVector* psMatrixToVector(
+    psVector* outVector,               ///< Vector to return, or NULL.
+    psImage* inImage                   ///< Image to convert.
+);
+
+/** Convert vector to matrix.
+ *
+ *  Converts a vector into a psImage matrix. If the dimensionality of the vector is PS_DIMEN_VECTOR, then the
+ *  resulting psImage is a 1d column. If the dimensionality of the vector is PS_DIMEN_TRANSV, then the
+ *  resulting psImage is a 1d row. If the user specifies NULL as the outImage argument,  then it will 
+ *  automatically be created. This function operates only with the psF64 data type.  
+ *
+ *  @return  psVector* : Pointer to psIamge.
+ */
+psImage* psVectorToMatrix(
+    psImage* outImage,                 ///< Matrix to return, or NULL.
+    psVector* inVector                 ///< Vector to convert.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/math/psMinimize.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psMinimize.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psMinimize.c	(revision 1553)
@@ -0,0 +1,940 @@
+
+/** @file  psMinimize.c
+ *  \brief basic minimization functions
+ *  @ingroup Math
+ *
+ *  This file will contain functions to minimize an arbitrary function at
+ *  a data point, fit an arbitrary function to a set of data points, and
+ *  fit a 1-D polynomial to a set of data points.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 03:17:03 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************/
+
+/* INCLUDE FILES                                                             */
+
+/*****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include <gsl/gsl_multifit_nlin.h>
+#include <gsl/gsl_multimin.h>
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include "psMatrix.h"
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+#define MAX_LMM_ITERATIONS 100
+#define MAX_MINIMIZE_ITERATIONS 100
+
+/** Preprocessor macro to generate error on a NULL 1DPolynomial */
+#define PS_CHECK_NULL_1DPOLY(NAME)                                                          \
+if (NAME == NULL || NAME->coeff == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error on a NULL vector */
+#define PS_CHECK_NULL_VECTOR(NAME)                                                          \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_EMPTY_VECTOR(NAME)                                                          \
+if (NAME->n < 1) {                                                                                  \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME);                             \
+}
+
+/** Preprocessor macro to generate error on differing size vectors */
+#define PS_CHECK_VECTOR_SIZE_EQUAL(VEC1, VEC2)                                                          \
+if (VEC1->n != VEC2->n) {               \
+    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
+}
+
+/** Preprocessor macro to generate error on a NULL image */
+#define PS_CHECK_NULL_IMAGE(NAME)                                                           \
+if (NAME == NULL || NAME->data.V == NULL) {                                                         \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME);                          \
+}
+
+/** Preprocessor macro to generate error for zero length rows or columns */
+#define PS_CHECK_EMPTY_IMAGE(NAME)                                                           \
+if (NAME->numCols < 1 || NAME->numRows < 1) {                                                       \
+    psError(__func__,"Invalid operation: %s has zero rows or columns (%dx%d).", #NAME,              \
+            NAME->numCols, NAME->numRows);                                                          \
+}
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+typedef struct
+{
+    size_t n;                   // Number of data points points in domain.
+    int paramCount;             // Number of non-masked parameters.
+    psVector* restrict initialGuess;
+    const psImage* restrict domain;
+    const psVector* restrict data;
+    const psVector* restrict errors;
+    const psVector* restrict paramMask;
+    psMinimizeFunction evalModel;
+    psMinimizeFunctionDeriv d_evalModel;
+}
+psMinChi2Data;
+
+typedef struct
+{
+    int paramCount;             // Number of non-masked parameters.
+    psVector* restrict initialGuess;
+    const psVector* restrict coord;
+    const psVector* restrict paramMask;
+    psMinimizeFunction evalModel;
+    psMinimizeFunctionDeriv d_evalModel;
+}
+psMinimizeData;
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+/******************************************************************************
+p_psMinFunc(*params, *funcData): We use the GSL procedure
+gsl_multimin_fdfminimizer_iterate() to minimize an arbitary function supplied
+by the user.  That GSL procedure requires the function to be minimized to be
+in a different format than the psLib format.  The purpose of this procedure
+is to serve as a GSL-format wrapper for the user-supplied procedure which is
+to be minimized.
+ 
+    params: The parameters of the function to be minimized.  These will be
+ varied by GSL in order to minimize the function.
+ 
+    funcData: a private psLib struct which contains the data point to be
+ minimized, the function and derivative function pointers, an initial
+ guess at the parameters, an option parameter mask, etc.
+ *****************************************************************************/
+double p_psMinFunc(const gsl_vector * params, void *funcData)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psVector* restrict coord = ((psMinimizeData* ) funcData)->coord;
+    const psVector* restrict mask = ((psMinimizeData* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinimizeData* ) funcData)->initialGuess;
+    psMinimizeFunction evalModel = ((psMinimizeData* ) funcData)->evalModel;
+    psVector* inputParameterList = NULL;
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Call the user-supplied function.
+    tmpf = evalModel(inputParameterList, coord);
+
+    // Free allocated memory and return the value of the function.
+    psFree(inputParameterList);
+    return (tmpf);
+}
+
+/******************************************************************************
+p_psMinFuncDeriv(*params, *funcData):  a GSL-like wrapper for the
+user-supplied procedure which calculates the derviative of the function to be
+minimized.
+ 
+    params: The parameters of the function to be minimized.  These will be
+ varied by GSL in order to minimize the function.
+ 
+    funcData: a private psLib struct which contains the data point to be
+ minimized, the function and derivative function pointers, an initial
+ guess at the parameters, an option parameter mask, etc.
+ 
+    df: we calculate the derivative of the function w.r.t. to each parameter
+ in "params" and return those derivatives in this psVector.
+ *****************************************************************************/
+void p_psMinFuncDeriv(const gsl_vector * params, void *funcData, gsl_vector * df)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psVector* restrict coord = ((psMinimizeData* ) funcData)->coord;
+    const psVector* restrict mask = ((psMinimizeData* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinimizeData* ) funcData)->initialGuess;
+    psMinimizeFunctionDeriv d_evalModel = ((psMinimizeData* ) funcData)->d_evalModel;
+    psVector* inputParameterList = NULL;
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the derivative w.r.t. each parameter.
+    // NOTE: we can probably remove the calls for masked parameters.
+    for (i = 0; i < initialGuess->n; i++) {
+        tmpf = d_evalModel(inputParameterList, coord, i);
+        gsl_vector_set(df, i, tmpf);
+    }
+
+    // Free allocated memory.
+    psFree(inputParameterList);
+}
+
+/******************************************************************************
+    Compute both p_psMinFunc and p_psMinFuncDeriv together.
+ *****************************************************************************/
+void p_psMinFuncFuncDeriv(const gsl_vector * params, void *funcData, double *f, gsl_vector * df)
+{
+    *f = p_psMinFunc(params, funcData);
+    p_psMinFuncDeriv(params, funcData, df);
+}
+
+// The first argument to evalModel() and d_evalModel() specifies the data
+// point.  It must have the same size as the second dimension of *domain.
+// The second argument must have the same size as *initialGuess and
+// *paramMask.
+
+/******************************************************************************
+p_psMinChi2Func(*x, *funcData, *outdata): We use the GSL procedure
+gsl_multifit_fdfsolver_iterate() to fit an arbitrary function, supplied by
+the user, to a set of data points.  That GSL procedure requires the function
+to be fit to be in a different format than the psLib format.  The purpose of
+this procedure is to serve as a GSL-format wrapper for the user-supplied
+procedure which is to be fit to the data.
+ 
+    params: These are the parameters which are to be varied by GSL in order
+  to minimize chi2 over the data set.
+ 
+    funcData: this data structure contains the input values over which the
+  function will be evaluated, the expected value of the function at
+  those points, the amount of error tolerable at those points, a mask
+  vector which specifies which parameters to the function are to be
+  constant, and an initial guess at the parameters.
+ 
+    outData: The function is evaluated at each point, then subtract the
+  expected value and divide by the error.
+ *****************************************************************************/
+int p_psMinChi2Func(const gsl_vector * params, void *funcData, gsl_vector * outData)
+{
+    int i;                      // Loop index variable.
+    int j;                      // Loop index variable.
+    float tmpf;                 // Temporary floating point variable.
+    const psImage* restrict domain = ((psMinChi2Data* ) funcData)->domain;
+    const psVector* restrict data = ((psMinChi2Data* ) funcData)->data;
+    const psVector* restrict errors = ((psMinChi2Data* ) funcData)->errors;
+    const psVector* restrict mask = ((psMinChi2Data* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinChi2Data* ) funcData)->initialGuess;
+    psMinimizeFunction evalModel = ((psMinChi2Data* ) funcData)->evalModel;
+    psVector* inputParameterList = NULL;
+    psVector* tmpVecPtr = NULL;
+
+    tmpVecPtr = psVectorAlloc(domain->numCols, PS_TYPE_F32);
+
+    // The GSL routines will call this function with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the function at each data point.
+    for (i = 0; i < domain->numRows; i++) {
+        for (j = 0; j < domain->numCols; j++) {
+            tmpVecPtr->data.F32[j] = domain->data.F32[i][j];
+        }
+        tmpf = evalModel(tmpVecPtr, inputParameterList);
+
+        gsl_vector_set(outData, i, (tmpf - data->data.F32[i]) / errors->data.F32[i]);
+    }
+
+    // Free allocated memory.
+    psFree(inputParameterList);
+    psFree(tmpVecPtr);
+
+    return GSL_SUCCESS;
+}
+
+/******************************************************************************
+p_psMinChi2FuncDeriv(*x, *funcData, *outdata): a GSL-like wrapper for the
+user-supplied procedure which calculates the derviative of the function to be
+minimized.
+    params: These are the parameters which are to be varied by GSL in order
+  to minimize chi2 over the data set.
+ 
+    funcData: this data structure contains the input values over which the
+  function will be evaluated, the expected value of the function at
+  those points, the amount of error tolerable at those points, a mask
+  vector which specifies which parameters to the function are to be
+  constant, and an initial guess at the parameters.
+ 
+    J: The derivative is evaluated at each point and w.r.t. each parameter
+ and returned in this data structure.
+ *****************************************************************************/
+int p_psMinChi2FuncDeriv(const gsl_vector * params, void *funcData, gsl_matrix * J)
+{
+    const psImage* restrict domain = ((psMinChi2Data* ) funcData)->domain;
+    const psVector* restrict errors = ((psMinChi2Data* ) funcData)->errors;
+    const psVector* restrict mask = ((psMinChi2Data* ) funcData)->paramMask;
+    psVector* restrict initialGuess = ((psMinChi2Data* ) funcData)->initialGuess;
+    psVector* inputParameterList = NULL;
+    psVector* tmpVecPtr = NULL;
+    psMinimizeFunctionDeriv d_evalModel = ((psMinChi2Data* ) funcData)->d_evalModel;
+
+    size_t i;
+    int j;
+    float tmpf;
+
+    tmpVecPtr = psVectorAlloc(domain->numCols, PS_TYPE_F32);
+
+    // The GSL routines will call this functions with the masked parameters
+    // removed.  However, the user-supplied function (to be modified) does not
+    // have those parameters removed.  Here will create a new parameter list
+    // with the masked parameters added (we expand initialGuess).
+
+    inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32);
+    if (mask != NULL) {
+        j = 0;
+        for (i = 0; i < mask->n; i++) {
+            if (mask->data.U8[i] != 0) {
+                inputParameterList->data.F32[i] = initialGuess->data.F32[i];
+            } else {
+                inputParameterList->data.F32[i] = gsl_vector_get(params, j++);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            inputParameterList->data.F32[i] = gsl_vector_get(params, i);
+        }
+    }
+
+    // Evaluate the derivtaive at each data point, and w.r.t. each parameter.
+    for (i = 0; i < domain->numRows; i++) {
+        for (j = 0; j < tmpVecPtr->n; j++) {
+            tmpVecPtr->data.F32[j] = domain->data.F32[i][j];
+        }
+
+        for (j = 0; j < inputParameterList->n; j++) {
+            tmpf = d_evalModel(tmpVecPtr, inputParameterList, j);
+            gsl_matrix_set(J, i, j, (tmpf / errors->data.F32[i]));
+        }
+    }
+
+    psFree(inputParameterList);
+    psFree(tmpVecPtr);
+    return GSL_SUCCESS;
+}
+
+int p_psMinChi2FuncFuncDeriv(const gsl_vector * params, void *funcData, gsl_vector * f, gsl_matrix * J)
+{
+    p_psMinChi2Func(params, funcData, f);
+    p_psMinChi2FuncDeriv(params, funcData, J);
+
+    return GSL_SUCCESS;
+}
+
+/******************************************************************************
+p_psBuildSums1D(x, polyOrder, sums): this routine calculates the powers of
+input parameter "x" between 0 and input parameter polyOrder.  The result is
+returned as a psVector sums.
+ *****************************************************************************/
+void p_psBuildSums1D(double x, int polyOrder, psVector* sums)
+{
+    int i = 0;
+    double xSum = 0.0;
+
+    xSum = 1.0;
+    for (i = 0; i <= polyOrder; i++) {
+        sums->data.F64[i] = xSum;
+        xSum *= x;
+    }
+}
+
+/******************************************************************************
+p_psBuildSums1D(x): this routine returns a psVector with "x" elements.  The
+values of the vector will be scaled uniformly between -1.0 and 1.0.
+ *****************************************************************************/
+psVector* psBuildImageScalingFactors(int x)
+{
+    int i = 0;                  // loop index variable.
+    psVector* imageScalingFactors = NULL;
+
+    imageScalingFactors = psVectorAlloc(x, PS_TYPE_F32);
+
+    for (i = 0; i < x; i++) {
+        imageScalingFactors->data.F32[i] = (((float)2 * i) / ((float)x)) - 1.0;
+    }
+
+    return (imageScalingFactors);
+}
+
+/******************************************************************************
+CURRENTLY NOT IN USE.
+ 
+p_psPolyOrderCheck(A, N, *indx, *B, polyOrder,*flag) This routine checks if
+all polyOrder-th terms in the polyOrder-th order sky background polynomial
+defined by the coefficients in the array B[] are consistent with zero.  If
+true, then *flag is set to 1.  Otherwise, *flag is set to 0.  The matrix
+inversion code in the middle of this procedure draws from Numerical Recipes
+in C page 48.
+Input:
+    A       This is the LUD decomposition of the original matrix A.
+    N       The size of the matrix (plus 1, actually, since offset 1).
+    indx    misc Numerical Recipes data structure.
+    B       The coefficients of the sky polynomial.
+    polyOrder The degree of the sky polynomial.
+Output:
+    *flag   Set this to 1 if we must recalculate the coefficients.
+ *****************************************************************************/
+void p_psPolyOrderCheck(float **A, int N, int *indx, float *B, int polyOrder, int *flag)
+{
+    float **y = NULL;           // This 2-D matrix will hold A^-1
+    float *col = NULL;          // misc NumerRecipes data structure
+    float *error = NULL;        // will hold the sqrt() of the
+
+    // diagonal of y[][].
+    int i = 0;                  // loop-index variable
+    int j = 0;                  // loop-index variable
+    int numPolyTerms = 0;       // The number of terms in the
+
+    // polynomial.
+    int lastTerm = 0;           // The index location of the first
+
+    // n-th order term in array B[].
+    int firstTerm = 0;          // Index location of last such term.
+
+    // Allocate the necessary data structures for this procedure...
+    error = (float *)psAlloc((N + 1) * sizeof(float));
+    col = (float *)psAlloc((N + 1) * sizeof(float));
+    y = (float **)psAlloc((N + 1) * sizeof(float *));
+    for (i = 1; i <= N; i++) {
+        y[i] = (float *)psAlloc((N + 1) * sizeof(float));
+    }
+
+    // Invert the matrix A and put the result in y[][].  This code is taken
+    // from Numerical Recipes in C page 48.
+    for (j = 1; j <= N; j++) {
+        for (i = 1; i <= N; i++) {
+            col[i] = 0.0;
+        }
+        col[j] = 1.0;
+        // NOTE: substitue the LUD rotine
+        // lubksb(A, N, indx, col);
+        for (i = 1; i <= N; i++) {
+            y[i][j] = col[i];
+        }
+    }
+
+    // Determine where the first n-th order (in this comment, n equals
+    // polyOrder) polynomial term is stored in the matrix B[], and also were
+    // the last n-order term is stored.  Then we loop over all the n-order
+    // terms and check if they are consistent with zero.
+
+    numPolyTerms = (((polyOrder + 1) * (polyOrder + 2)) / 2);
+    lastTerm = numPolyTerms + 1;
+    firstTerm = lastTerm - polyOrder;
+    *flag = 1;
+    for (i = firstTerm; i <= lastTerm; i++) {
+        #ifdef DARWIN
+        error[i] = (float)sqrt(y[i][i]);
+        #else
+
+        error[i] = sqrtf(y[i][i]);
+        #endif
+
+        if (!((B[i] <= (2.0f * error[i])) && ((-2.0f * error[i]) <= B[i]))) {
+            *flag = 0;
+        }
+    }
+
+    // Free all memory allocated in this routine.
+    psFree(error);
+    psFree(col);
+    for (j = 1; j <= N; j++) {
+        psFree(y[j]);
+    }
+    psFree(y);
+}
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+/******************************************************************************
+psMinimize(initialGuess, myFunction, myFunctionDeriv, coord, paramMask):
+ 
+This routine must minimize an arbitrary function; it determines the set of
+parameters of that function such that the ...
+ *****************************************************************************/
+psVector* psMinimize(psVector* restrict initialGuess,
+                     psMinimizeFunction myFunction,
+                     psMinimizeFunctionDeriv myFunctionDeriv,
+                     const psVector* restrict coord,
+                     const psVector* restrict paramMask)
+{
+    int status;
+    int i = 0;
+    int j = 0;
+    int iter = 0;
+    gsl_multimin_function_fdf f;
+    const gsl_multimin_fdfminimizer_type *T;
+    gsl_multimin_fdfminimizer *s;
+    psMinimizeData inputData;
+    gsl_vector *x;
+
+    PS_CHECK_NULL_VECTOR(initialGuess);
+    PS_CHECK_EMPTY_VECTOR(initialGuess);
+    PS_CHECK_NULL_VECTOR(coord);
+    PS_CHECK_EMPTY_VECTOR(coord);
+    if (paramMask != NULL) {
+        PS_CHECK_NULL_VECTOR(paramMask);
+        PS_CHECK_EMPTY_VECTOR(paramMask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(initialGuess, paramMask);
+    }
+
+    inputData.initialGuess = initialGuess;
+    inputData.coord = coord;
+    inputData.paramMask = paramMask;
+    inputData.evalModel = myFunction;
+    inputData.d_evalModel = myFunctionDeriv;
+    inputData.paramCount = 0;
+
+    // If the user supplied a parameter mask, then count the number of
+    // non-masked elements.  This will be used later in allocating a vector
+    // for the parameters.
+    if (paramMask != NULL) {
+        for (i = 0; i < paramMask->n; i++) {
+            if (paramMask->data.U8[i] != 0) {
+                inputData.paramCount++;
+            }
+        }
+    } else {
+        inputData.paramCount = initialGuess->n;
+    }
+
+    // The initial guess at the parameters for the function are written into
+    // the vector inputParameterList.  If the paramMask is not NULL, then
+    // masked parameters are masked out.
+    x = gsl_vector_alloc(inputData.paramCount);
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                gsl_vector_set(x, j++, initialGuess->data.F32[i]);
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            gsl_vector_set(x, i, initialGuess->data.F32[i]);
+        }
+    }
+    f.f = &p_psMinFunc;
+    f.df = &p_psMinFuncDeriv;
+    f.fdf = &p_psMinFuncFuncDeriv;
+    f.n = inputData.paramCount;
+    f.params = &inputData;
+
+    T = gsl_multimin_fdfminimizer_conjugate_fr;
+    s = gsl_multimin_fdfminimizer_alloc(T, inputData.paramCount);
+    gsl_multimin_fdfminimizer_set(s, &f, x, 0.01, 1e-4);
+    do {
+        iter++;
+        status = gsl_multimin_fdfminimizer_iterate(s);
+
+        if (status)
+            break;
+
+        status = gsl_multimin_test_gradient(s->gradient, 1e-3);
+
+        if (status == GSL_SUCCESS)
+            printf("Minimum found at:\n");
+
+    } while (status == GSL_CONTINUE && iter < MAX_MINIMIZE_ITERATIONS);
+
+    // In the above steps we had removed the masked elements from the
+    // the solver.  This next code blocks puts those masked elements
+    // into the solution.
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                initialGuess->data.F32[i] = gsl_vector_get(s->x, j++);
+            } else {
+                initialGuess->data.F32[i] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            initialGuess->data.F32[i] = gsl_vector_get(s->x, i);
+        }
+    }
+    return (initialGuess);
+}
+
+/******************************************************************************
+    This routine must determine the parameters of an arbitrary function
+    such that they best fit the supplied data points.
+ *****************************************************************************/
+psVector* psMinimizeChi2(psMinimizeFunction evalModel,
+                         psMinimizeFunctionDeriv DevalModel,
+                         const psImage* restrict domain,
+                         const psVector* restrict data,
+                         const psVector* restrict errors,
+                         psVector* restrict initialGuess,
+                         const psVector* restrict paramMask,
+                         float *chiSq)
+{
+    int numData = domain->numRows;      // Number of data points
+    int status;                 // Return status for the GSL solver.
+    int i = 0;                  // Loop index variable.
+    int j = 0;                  // Loop index variable.
+    int iter = 0;               // Iteration counter.
+    gsl_multifit_function_fdf f;        // GSL structure that contains the
+
+    // functions/derivative to be solved.
+    double *xInit = NULL;       // The initial guess at the parameters
+
+    // with masked parameters removed.
+    const gsl_multifit_fdfsolver_type *T;
+
+    // This tells GSL to use the Levenberg-
+    // Marquardt algorithm for chi2
+    // minimization.
+    gsl_multifit_fdfsolver *s;  // GSL data structure.
+    psMinChi2Data inputData;
+    float chiSqOld = 0.0;
+
+    PS_CHECK_NULL_IMAGE(domain);
+    PS_CHECK_EMPTY_IMAGE(domain);
+    PS_CHECK_NULL_VECTOR(data);
+    PS_CHECK_EMPTY_VECTOR(data);
+    PS_CHECK_NULL_VECTOR(errors);
+    PS_CHECK_EMPTY_VECTOR(errors);
+    PS_CHECK_NULL_VECTOR(initialGuess);
+    PS_CHECK_EMPTY_VECTOR(initialGuess);
+    PS_CHECK_VECTOR_SIZE_EQUAL(data, errors);
+    if (domain->numRows != data->n) {
+        psAbort(__func__, "Number of data points and data values not equal.");
+    }
+    if (paramMask != NULL) {
+        PS_CHECK_NULL_VECTOR(paramMask);
+        PS_CHECK_EMPTY_VECTOR(paramMask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(initialGuess, paramMask);
+    }
+
+    inputData.n = numData;
+    inputData.paramCount = 0;
+    inputData.initialGuess = initialGuess;
+    inputData.domain = domain;
+    inputData.data = data;
+    inputData.errors = errors;
+    inputData.paramMask = paramMask;
+    inputData.evalModel = evalModel;
+    inputData.d_evalModel = DevalModel;
+
+    // If the user supplied a parameter mask, then count the number of
+    // non-masked elements.  This will be used later in allocating a vector
+    // for the parameters.
+    if (paramMask != NULL) {
+        for (i = 0; i < paramMask->n; i++) {
+            if (paramMask->data.U8[i] != 0) {
+                inputData.paramCount++;
+            }
+        }
+    } else {
+        inputData.paramCount = initialGuess->n;
+    }
+
+    // The initial guess at the parameters for the function are written into
+    // the vector inputParameterList.  If the paramMask is not NULL, then those
+    // parameters are masked out.
+    xInit = (double *)psAlloc(inputData.paramCount * sizeof(double));
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                xInit[j++] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            xInit[i] = initialGuess->data.F32[i];
+        }
+    }
+
+    const gsl_rng_type *type;
+    gsl_rng *r;
+
+    gsl_rng_env_setup();
+
+    type = gsl_rng_default;
+    r = gsl_rng_alloc(type);
+
+    // Initialize the main data structure used by the GSL solver.  This will
+    // contain pointers to the function to be minimized, it's derivative
+    // function, the number of data points, the number of free parameters,
+    // and the data structures those functions use.
+
+    f.f = &p_psMinChi2Func;
+    f.df = &p_psMinChi2FuncDeriv;
+    f.fdf = &p_psMinChi2FuncFuncDeriv;
+    f.n = numData;
+    f.p = inputData.paramCount;
+    f.params = &inputData;
+
+    gsl_vector_view x = gsl_vector_view_array(xInit, inputData.paramCount);
+
+    T = gsl_multifit_fdfsolver_lmsder;
+    s = gsl_multifit_fdfsolver_alloc(T, numData, inputData.paramCount);
+    gsl_multifit_fdfsolver_set(s, &f, &x.vector);
+    *chiSq = 0.0;
+    chiSqOld = 0.0;
+    do {
+        iter++;
+        for (i = 0; i < initialGuess->n; i++) {
+            printf("Iteration %d: parameter %d is %.3f\n", iter, i, gsl_vector_get(s->x, i));
+        }
+        // Perform an iteration of the GSL solver.
+        status = gsl_multifit_fdfsolver_iterate(s);
+        printf("gsl_multifit_fdfsolver_iterate() status is %s\n", gsl_strerror(status));
+        for (i = 0; i < initialGuess->n; i++) {
+            printf("Iteration %d: parameter %d is %.3f\n", iter, i, gsl_vector_get(s->x, i));
+        }
+
+        // If there was a problem, abort.
+        if (status) {
+            psAbort(__func__, "gsl_multifit_fdfsolver_iterate(%s)\n", gsl_strerror(status));
+        }
+        // Test if the parameters changed by a small enough amount.
+        // NOTE: This wasn't working right when the parameters fit exactly.
+        // Figure out why.
+        // status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
+
+        // We test for convergence if chiSquared changes by less than 1.0
+        // as specified in the ADD.
+        *chiSq = gsl_blas_dnrm2(s->f);
+        printf("psMinimize.c: chiSq is %.3f\n", *chiSq);
+        if (fabs(*chiSq - chiSqOld) < 1.0) {
+            status = GSL_SUCCESS;
+        } else {
+            status = GSL_CONTINUE;
+        }
+        chiSqOld = *chiSq;
+
+    } while (status == GSL_CONTINUE && iter < MAX_LMM_ITERATIONS);
+
+    // In the above steps we had removed the masked elements from the
+    // the solver.  This next code blocks puts those masked elements
+    // into the solution.
+    if (paramMask != NULL) {
+        j = 0;
+        for (i = 0; i < initialGuess->n; i++) {
+            if (paramMask->data.U8[i] == 0) {
+                initialGuess->data.F32[i] = gsl_vector_get(s->x, j++);
+            } else {
+                initialGuess->data.F32[i] = initialGuess->data.F32[i];
+            }
+        }
+    } else {
+        for (i = 0; i < initialGuess->n; i++) {
+            initialGuess->data.F32[i] = gsl_vector_get(s->x, i);
+        }
+    }
+
+    // Calculate the chi-squared for the derived solution.
+    *chiSq = gsl_blas_dnrm2(s->f);
+
+    // Free all allocated memory
+    // NOTE: Free x.
+    gsl_multifit_fdfsolver_free(s);
+    psFree(xInit);
+
+    // Bye bye.
+    return (initialGuess);
+}
+
+/******************************************************************************
+    This routine must fit a polynomial of degree myPoly to the data points
+    (x, y) and return the coefficients of that polynomial, as well as the
+    error for each data point (yErr).
+ 
+NOTE: yErr is currently ignored.
+ *****************************************************************************/
+psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* myPoly,
+                                        const psVector* restrict x,
+                                        const psVector* restrict y, const psVector* restrict yErr)
+{
+    int polyOrder = myPoly->n;
+    psImage* A = NULL;
+    psImage* ALUD = NULL;
+    psVector* B = NULL;
+    psVector* outPerm = NULL;
+    psVector* X = NULL;         // NOTE: do we need this?
+    psVector* coeffs = NULL;
+    int i = 0;
+    int j = 0;
+    int k = 0;
+    psVector* xSums = NULL;
+
+    // printf("psVectorFitPolynomial1D()\n");
+    // for (i=0;i<x->n;i++) {
+    // printf("(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]);
+    // }
+
+    PS_CHECK_NULL_1DPOLY(myPoly);
+    PS_CHECK_NULL_VECTOR(x);
+    PS_CHECK_EMPTY_VECTOR(x);
+    PS_CHECK_NULL_VECTOR(y);
+    PS_CHECK_EMPTY_VECTOR(y);
+    PS_CHECK_NULL_VECTOR(yErr);
+    PS_CHECK_EMPTY_VECTOR(yErr);
+    PS_CHECK_VECTOR_SIZE_EQUAL(x, y);
+    PS_CHECK_VECTOR_SIZE_EQUAL(y, yErr);
+
+    A = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
+    ALUD = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
+    B = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    coeffs = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    X = psVectorAlloc(x->n, PS_TYPE_F64);
+    outPerm = psVectorAlloc(polyOrder, PS_TYPE_F64);
+    xSums = psVectorAlloc(1 + 2 * polyOrder, PS_TYPE_F64);
+
+    // Initialize data structures.
+    for (i = 0; i < (polyOrder); i++) {
+        B->data.F64[i] = 0.0;
+        coeffs->data.F64[i] = 0.0;
+        outPerm->data.F64[i] = 0.0;
+        for (j = 0; j < (polyOrder); j++) {
+            A->data.F64[i][j] = 0.0;
+            ALUD->data.F64[i][j] = 0.0;
+        }
+    }
+    for (i = 0; i < X->n; i++) {
+        X->data.F64[i] = x->data.F64[i];
+    }
+
+    // Build the B and A data structs.
+    for (i = 0; i < X->n; i++) {
+        p_psBuildSums1D(X->data.F64[i], 2 * polyOrder, xSums);
+
+        for (k = 0; k < (polyOrder); k++) {
+            B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k];
+        }
+
+        for (k = 0; k < (polyOrder); k++) {
+            for (j = 0; j < (polyOrder); j++) {
+                A->data.F64[k][j] += xSums->data.F64[k + j];
+            }
+        }
+    }
+
+    ALUD = psMatrixLUD(ALUD, outPerm, A);
+    coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+
+    for (k = 0; k < (polyOrder); k++) {
+        myPoly->coeff[k] = coeffs->data.F64[k];
+        // printf("myPoly->coeff[%d] is %f\n", k, myPoly->coeff[k]);
+    }
+
+    // for (i=0;i<x->n;i++) {
+    // printf("HMMM: psEvalPolynomial1D(%f) is %f\n", x->data.F64[i], psEvalPolynomial1D(x->data.F64[i],
+    // myPoly));
+    // }
+
+    psFree(A);
+    psFree(ALUD);
+    psFree(B);
+    psFree(coeffs);
+    psFree(X);
+    psFree(outPerm);
+    psFree(xSums);
+
+    return (myPoly);
+}
Index: /tags/rel2_1/psLib/src/math/psMinimize.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psMinimize.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psMinimize.h	(revision 1553)
@@ -0,0 +1,105 @@
+#if !defined(PS_MINIMIZE_H)
+#define PS_MINIMIZE_H
+
+#include "psFunctions.h"
+
+/** \file psMinimize.h
+ *  \brief minimization operations
+ *  \ingroup Stats
+ */
+
+/** Functions **************************************************************/
+
+/** \addtogroup Stats
+ *  \{
+ */
+
+/** function of a collection of parameters and coordinate vector.
+ *
+ *  @return float    value to minimize
+ */
+typedef float (*psMinimizeFunction)(
+    const psVector* restrict params,   ///< collection of parameters
+    const psVector* restrict coord     ///< coordinates
+);
+
+/** derivative function of psMinimizeFunction
+ *
+ *  @return float     the derivative in respect to params[derivParam]
+ */
+typedef float (*psMinimizeFunctionDeriv) (
+    const psVector* restrict params,   ///< collection of parameters
+    const psVector* restrict coord,    ///< coordinates
+    int derivParam                     ///< index of parameter to calculate derivative of
+);
+
+/** Minimizes a non-linear function.
+ *
+ *  psMinimize determines and returns the vector that minimizes the specified 
+ *  function. It takes as input a function, myFunction, an initial guess for
+ *  the vector that minimizes the function, initialGuess, the current 
+ *  coordiate coord, and an optional mask for the vector elements (function 
+ *  parameters) to minimize, paramMask (all parameters are fit if PSLib SDRS 
+ *  25 July 13, 2004 Pan-STARRS Image Processing Pipeline PSDC-430-007-04 
+ *  NULL). Note that paramMask must be of type psU8, while params must be of 
+ *  type psF32. The optional function, myFuncDeriv returns the derivative of 
+ *  the function. This function must be valid only for types psF32, psF64.
+ *
+ *  @return psVector*    minimized vector
+ */
+psVector* psMinimize(
+    psVector* restrict initialGuess,
+    psMinimizeFunction myFunction,
+    psMinimizeFunctionDeriv myFunctionDeriv,
+    const psVector* restrict coord,
+    const psVector* restrict paramMask
+);
+
+/** Minimize chi^2 for input data.
+ *
+ *  psMinimizeChi2 fits a model to observations by minimizing chi^2, returning 
+ *  the best-fit parameters. The input parameters are a function that 
+ *  evaluates the model for a specified domain, given the parameters, 
+ *  evalModel; a list of observations, (domain, data, and errors); an initial 
+ *  guess at the best-fit parameters, initialGuess which is returned with the 
+ *  best-fit parameters, and an optional mask specifying which parameters are 
+ *  to be fit, paramMask, which must be of type psU8. All parameters are fit 
+ *  if this vector is NULL. This function must be valid only for types psF32, 
+ *  psF64.
+ *
+ *  @return psVector*      minimized vector
+ */
+psVector* psMinimizeChi2(
+    psMinimizeFunction evalModel,      ///< Model to fit; (domain and params)
+    psMinimizeFunctionDeriv DevalModel,///< Derivative of model to fit; (domain and params)
+    const psImage* restrict domain,    ///< The domain values for the corresponding measurements
+    const psVector* restrict data,     ///< Data to fit
+    const psVector* restrict errors,   ///< Errors in the data
+    psVector* restrict initialGuess,   ///< Initial guess
+    const psVector* restrict paramMask,///< 1 = fit for parameter, 0 = hold parameter constant
+    float *chiSq                       ///< chi squared
+);
+
+/** Derive a polynomial fit by chi^2 minimisation (analytically)
+ *
+ *  psVectorFitPolynomial1d returns the polynomial that best fits the 
+ *  observations. The input parameters are a polynomial that specifies the 
+ *  fit order, myPoly, which will be altered and returned with the best-fit 
+ *  coefficients; and the observations, x, y and yErr. The independent 
+ *  variable list, x may be NULL, in which case the vector index is used. 
+ *  The dependent variable error, yErr may be null, in which case the solution 
+ *  is determined in the assumption that all data errors are equal. This 
+ *  function must be valid only for types psF32, psF64.
+ *
+ *  @return psPolynomial1D*    polynomial fit
+ */
+psPolynomial1D* psVectorFitPolynomial1D(
+    psPolynomial1D* myPoly,            ///< Polynomial to fit
+    const psVector* restrict x,        ///< Ordinates (or NULL to just use the indices)
+    const psVector* restrict y,        ///< Coordinates
+    const psVector* restrict yErr      ///< Errors in coordinates, or NULL
+);
+
+/* \} */// End of MathGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/math/psPolynomial.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psPolynomial.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psPolynomial.c	(revision 1553)
@@ -0,0 +1,770 @@
+
+/** @file  psFunctions.c
+ *
+ *  @brief Contains basic function allocation, deallocation, and evaluation
+ *         routines.
+ *
+ *  This file will hold the functions for allocated, freeing, and evaluating
+ *  polynomials.  It also contains a Gaussian functions.
+ *
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:07:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************/
+
+/*  INCLUDE FILES                                                            */
+
+/*****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psFunctions.h"
+
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+static void polynomial1DFree(psPolynomial1D* myPoly);
+static void polynomial2DFree(psPolynomial2D* myPoly);
+static void polynomial3DFree(psPolynomial3D* myPoly);
+static void polynomial4DFree(psPolynomial4D* myPoly);
+static void dPolynomial1DFree(psDPolynomial1D* myPoly);
+static void dPolynomial2DFree(psDPolynomial2D* myPoly);
+static void dPolynomial3DFree(psDPolynomial3D* myPoly);
+static void dPolynomial4DFree(psDPolynomial4D* myPoly);
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - PUBLIC                                         */
+
+/*****************************************************************************/
+
+/*****************************************************************************
+    Evaluate a non-normalized Gaussian with the given mean and sigma at the
+    given coordianate.  Note that this is not a Gaussian deviate.  The
+    evaluated Gaussian is: \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
+ *****************************************************************************/
+float psGaussian(float x, float mean, float sigma, bool normal)
+{
+    float tmp = 1.0;
+
+    if (normal == true) {
+        #ifdef DARWIN
+        tmp = 1.0 / (float)sqrt(2.0 * M_PI * (sigma * sigma));
+        #else
+
+        tmp = 1.0 / sqrtf(2.0 * M_PI * (sigma * sigma));
+        #endif
+
+    }
+
+    return (tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma)));
+}
+
+/*****************************************************************************
+    psGaussianDev()
+ This routine creates a psVector of the specified size and type F32
+ and fills it with a random Gaussian distribution of numbers with
+ the specified mean and sigma.  This routine makes use of the GSL
+ routines for generating both uniformly distributed numbers and the
+ Gaussian distribution as well.
+ 
+ NOTE: There is no way to seed the random generator.
+ *****************************************************************************/
+psVector* psGaussianDev(float mean, float sigma, int Npts)
+{
+    psVector* gauss = NULL;
+    const gsl_rng_type *T = NULL;
+    gsl_rng *r = NULL;
+    int i = 0;
+
+    gauss = psVectorAlloc(Npts, PS_TYPE_F32);
+    gauss->n = Npts;
+    gsl_rng_env_setup();
+    T = gsl_rng_default;
+    r = gsl_rng_alloc(T);
+
+    for (i = 0; i < Npts; i++) {
+        gauss->data.F32[i] = mean + gsl_ran_gaussian(r, sigma);
+    }
+
+    // NOTE: Should I free r as well?
+    return (gauss);
+}
+
+/*****************************************************************************
+    This routine must allocate memory for the polynomial structures.
+ *****************************************************************************/
+psPolynomial1D* psPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psPolynomial1D* newPoly = NULL;
+
+    newPoly = (psPolynomial1D* ) psAlloc(sizeof(psPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (float *)psAlloc(n * sizeof(float));
+    newPoly->coeffErr = (float *)psAlloc(n * sizeof(float));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psPolynomial2D* psPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psPolynomial2D* newPoly = NULL;
+
+    newPoly = (psPolynomial2D* ) psAlloc(sizeof(psPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->coeffErr = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->coeffErr[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial3D* psPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial3D* newPoly = NULL;
+
+    newPoly = (psPolynomial3D* ) psAlloc(sizeof(psPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->coeffErr = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->coeffErr[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->coeffErr[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial4D* psPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial4D* newPoly = NULL;
+
+    newPoly = (psPolynomial4D* ) psAlloc(sizeof(psPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->coeffErr = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->coeffErr[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->coeffErr[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->coeffErr[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void polynomial1DFree(psPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial2DFree(psPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial3DFree(psPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial4DFree(psPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ 
+    XXX: Determine, from IfA, whether ot not the "mask[]" terms should be used
+    in polynomial evaluation.  If so, then all of the following polynomial
+    evaluation functions must be modified to do so.
+ 
+    XXX: Should the "coeffErr[]" should be used as well?
+ *****************************************************************************/
+float psPolynomial1DEval(float x, const psPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+
+    if (NULL == myPoly) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly is NULL\n");
+    }
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    if (NULL == myPoly->coeff) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly->coeff is NULL\n");
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial2DEval(float x, float y, const psPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial3DEval(float x, float y, float z, const psPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial4DEval(float w, float x, float y, float z, const psPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float wSum = 1.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
+
+psDPolynomial1D* psDPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psDPolynomial1D* newPoly = NULL;
+
+    newPoly = (psDPolynomial1D* ) psAlloc(sizeof(psDPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (double *)psAlloc(n * sizeof(double));
+    newPoly->coeffErr = (double *)psAlloc(n * sizeof(double));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial2D* psDPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psDPolynomial2D* newPoly = NULL;
+
+    newPoly = (psDPolynomial2D* ) psAlloc(sizeof(psDPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->coeffErr = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->coeffErr[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial3D* psDPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial3D* newPoly = NULL;
+
+    newPoly = (psDPolynomial3D* ) psAlloc(sizeof(psDPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->coeffErr = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->coeffErr[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->coeffErr[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial4D* psDPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial4D* newPoly = NULL;
+
+    newPoly = (psDPolynomial4D* ) psAlloc(sizeof(psDPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->coeffErr = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->coeffErr[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->coeffErr[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->coeffErr[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void dPolynomial1DFree(psDPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial2DFree(psDPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial3DFree(psDPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial4DFree(psDPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ *****************************************************************************/
+double psDPolynomial1DEval(double x, const psDPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial2DEval(double x, double y, const psDPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial3DEval(double x, double y, double z, const psDPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial4DEval(double w, double x, double y, double z, const psDPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double wSum = 1.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
Index: /tags/rel2_1/psLib/src/math/psPolynomial.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psPolynomial.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psPolynomial.h	(revision 1553)
@@ -0,0 +1,318 @@
+
+/** @file psFunctions.h
+*  \brief Standard Mathematical Functions.
+*  \ingroup Stats
+*
+*  This file will hold the prototypes for procedures which allocate, free,
+*  and evaluate various polynomials.  Those polynomial structures are also
+*  defined here.
+*
+*  @ingroup Stats
+*
+*  @author Someone at IfA
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-11 02:35:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#if !defined(PS_FUNCTIONS_H)
+#define PS_FUNCTIONS_H
+
+#include <stdbool.h>
+
+#include "psVector.h"
+
+/** \addtogroup Stats
+ *  \{
+ */
+
+/** Evaluate a non-normalized Gaussian with the given mean and sigma at the
+ *  given coordianate.  
+ *
+ *  Note that this is not a Gaussian deviate.  The evaluated Gaussian is: 
+ *        \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f] 
+ *
+ *  @return float      value on the gaussian curve given the input parameters
+ */
+float psGaussian(
+    float x,                           ///< Value at which to evaluate
+    float mean,                        ///< Mean for the Gaussian
+    float stddev,                      ///< Standard deviation for the Gaussian
+    bool normal                        ///< Indicates whether result should be normalized
+);
+
+/** Produce a vector of random numbers from a Gaussian distribution with
+ *  the specified mean and sigma 
+ *  
+ *  @return psVector*    vector of random numbers
+ *  
+ */
+psVector* psGaussianDev(
+    float mean,                        ///< The mean of the Gaussian
+    float sigma,                       ///< The sigma of the Gaussian
+    int Npts                           ///< The size of the vector
+);
+
+/** One-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    float *coeff;                      ///< Coefficients
+    float *coeffErr;                   ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psPolynomial1D;
+
+/** Two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    float **coeff;                     ///< Coefficients
+    float **coeffErr;                  ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psPolynomial2D;
+
+/** Three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ***coeff;                    ///< Coefficients
+    float ***coeffErr;                 ///< Error in coefficients
+    char ***mask;                      ///< Coefficients mask
+}
+psPolynomial3D;
+
+/** Four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ****coeff;                   ///< Coefficients
+    float ****coeffErr;                ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psPolynomial4D;
+
+
+/** Allocates a psPolynomial1D structure with n terms
+ *
+ *  @return  psPolynomial1D*    new 1-D polynomial struct
+ */
+psPolynomial1D* psPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new 2-D polynomial struct
+ */
+psPolynomial2D* psPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new 3-D polynomial struct
+ */
+psPolynomial3D* psPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new 4-D polynomial struct
+ */
+psPolynomial4D* psPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial1DEval(
+    float x,                           ///< location at which to evaluate
+    const psPolynomial1D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial2DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    const psPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial3DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial3D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial4DEval(
+    float w,                           ///< w location at which to evaluate
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial4D* myPoly       ///< Coefficients for the polynomial
+);
+
+/*****************************************************************************/
+
+/* Double-precision polynomials, mainly for use in astrometry */
+
+/** Double-precision one-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    double *coeff;                     ///< Coefficients
+    double *coeffErr;                  ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psDPolynomial1D;
+
+/** Double-precision two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    double **coeff;                    ///< Coefficients
+    double **coeffErr;                 ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psDPolynomial2D;
+
+/** Double-precision three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ***coeff;                   ///< Coefficients
+    double ***coeffErr;                ///< Error in coefficients
+    char ***mask;                      ///< Coefficient mask
+}
+psDPolynomial3D;
+
+/** Double-precision four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ****coeff;                  ///< Coefficients
+    double ****coeffErr;               ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psDPolynomial4D;
+
+/** Allocates a double-precision 1-D polynomial structure with n terms
+ *
+ *  @return  psPolynomial1D*    new double-precision 1-D polynomial struct
+ */
+psDPolynomial1D* psDPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a double-precision 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new double-precision 2-D polynomial struct
+ */
+psDPolynomial2D* psDPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a double-precision 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new double-precision 3-D polynomial struct
+ */
+psDPolynomial3D* psDPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a double-precision 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new double-precision 4-D polynomial struct
+ */
+psDPolynomial4D* psDPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a double-precision 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial1DEval(
+    double x,                          ///< Value at which to evaluate
+    const psDPolynomial1D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial2DEval(
+    double x,                           ///< Value x at which to evaluate
+    double y,                           ///< Value y at which to evaluate
+    const psDPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial3DEval(
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial3D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial4DEval(
+    double w,                          ///< Value w at which to evaluate
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial4D* myPoly      ///< Coefficients for the polynomial
+);
+
+/* \} */// End of MathGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/math/psSpline.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psSpline.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psSpline.c	(revision 1553)
@@ -0,0 +1,770 @@
+
+/** @file  psFunctions.c
+ *
+ *  @brief Contains basic function allocation, deallocation, and evaluation
+ *         routines.
+ *
+ *  This file will hold the functions for allocated, freeing, and evaluating
+ *  polynomials.  It also contains a Gaussian functions.
+ *
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:07:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************/
+
+/*  INCLUDE FILES                                                            */
+
+/*****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psFunctions.h"
+
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+static void polynomial1DFree(psPolynomial1D* myPoly);
+static void polynomial2DFree(psPolynomial2D* myPoly);
+static void polynomial3DFree(psPolynomial3D* myPoly);
+static void polynomial4DFree(psPolynomial4D* myPoly);
+static void dPolynomial1DFree(psDPolynomial1D* myPoly);
+static void dPolynomial2DFree(psDPolynomial2D* myPoly);
+static void dPolynomial3DFree(psDPolynomial3D* myPoly);
+static void dPolynomial4DFree(psDPolynomial4D* myPoly);
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - PUBLIC                                         */
+
+/*****************************************************************************/
+
+/*****************************************************************************
+    Evaluate a non-normalized Gaussian with the given mean and sigma at the
+    given coordianate.  Note that this is not a Gaussian deviate.  The
+    evaluated Gaussian is: \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
+ *****************************************************************************/
+float psGaussian(float x, float mean, float sigma, bool normal)
+{
+    float tmp = 1.0;
+
+    if (normal == true) {
+        #ifdef DARWIN
+        tmp = 1.0 / (float)sqrt(2.0 * M_PI * (sigma * sigma));
+        #else
+
+        tmp = 1.0 / sqrtf(2.0 * M_PI * (sigma * sigma));
+        #endif
+
+    }
+
+    return (tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma)));
+}
+
+/*****************************************************************************
+    psGaussianDev()
+ This routine creates a psVector of the specified size and type F32
+ and fills it with a random Gaussian distribution of numbers with
+ the specified mean and sigma.  This routine makes use of the GSL
+ routines for generating both uniformly distributed numbers and the
+ Gaussian distribution as well.
+ 
+ NOTE: There is no way to seed the random generator.
+ *****************************************************************************/
+psVector* psGaussianDev(float mean, float sigma, int Npts)
+{
+    psVector* gauss = NULL;
+    const gsl_rng_type *T = NULL;
+    gsl_rng *r = NULL;
+    int i = 0;
+
+    gauss = psVectorAlloc(Npts, PS_TYPE_F32);
+    gauss->n = Npts;
+    gsl_rng_env_setup();
+    T = gsl_rng_default;
+    r = gsl_rng_alloc(T);
+
+    for (i = 0; i < Npts; i++) {
+        gauss->data.F32[i] = mean + gsl_ran_gaussian(r, sigma);
+    }
+
+    // NOTE: Should I free r as well?
+    return (gauss);
+}
+
+/*****************************************************************************
+    This routine must allocate memory for the polynomial structures.
+ *****************************************************************************/
+psPolynomial1D* psPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psPolynomial1D* newPoly = NULL;
+
+    newPoly = (psPolynomial1D* ) psAlloc(sizeof(psPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (float *)psAlloc(n * sizeof(float));
+    newPoly->coeffErr = (float *)psAlloc(n * sizeof(float));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psPolynomial2D* psPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psPolynomial2D* newPoly = NULL;
+
+    newPoly = (psPolynomial2D* ) psAlloc(sizeof(psPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->coeffErr = (float **)psAlloc(nX * sizeof(float *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->coeffErr[x] = (float *)psAlloc(nY * sizeof(float));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial3D* psPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial3D* newPoly = NULL;
+
+    newPoly = (psPolynomial3D* ) psAlloc(sizeof(psPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->coeffErr = (float ***)psAlloc(nX * sizeof(float **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->coeffErr[x] = (float **)psAlloc(nY * sizeof(float *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->coeffErr[x][y] = (float *)psAlloc(nZ * sizeof(float));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psPolynomial4D* psPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psPolynomial4D* newPoly = NULL;
+
+    newPoly = (psPolynomial4D* ) psAlloc(sizeof(psPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) polynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->coeffErr = (float ****)psAlloc(nW * sizeof(float ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->coeffErr[w] = (float ***)psAlloc(nX * sizeof(float **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->coeffErr[w][x] = (float **)psAlloc(nY * sizeof(float *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->coeffErr[w][x][y] = (float *)psAlloc(nZ * sizeof(float));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void polynomial1DFree(psPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial2DFree(psPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial3DFree(psPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void polynomial4DFree(psPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ 
+    XXX: Determine, from IfA, whether ot not the "mask[]" terms should be used
+    in polynomial evaluation.  If so, then all of the following polynomial
+    evaluation functions must be modified to do so.
+ 
+    XXX: Should the "coeffErr[]" should be used as well?
+ *****************************************************************************/
+float psPolynomial1DEval(float x, const psPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+
+    if (NULL == myPoly) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly is NULL\n");
+    }
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    if (NULL == myPoly->coeff) {
+        psAbort(__func__, "psPolynomial1DEval(): myPoly->coeff is NULL\n");
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial2DEval(float x, float y, const psPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial3DEval(float x, float y, float z, const psPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+float psPolynomial4DEval(float w, float x, float y, float z, const psPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    float polySum = 0.0;
+    float wSum = 1.0;
+    float xSum = 1.0;
+    float ySum = 1.0;
+    float zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
+
+psDPolynomial1D* psDPolynomial1DAlloc(int n)
+{
+    int i = 0;
+    psDPolynomial1D* newPoly = NULL;
+
+    newPoly = (psDPolynomial1D* ) psAlloc(sizeof(psDPolynomial1D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial1DFree);
+    newPoly->n = n;
+    newPoly->coeff = (double *)psAlloc(n * sizeof(double));
+    newPoly->coeffErr = (double *)psAlloc(n * sizeof(double));
+    newPoly->mask = (char *)psAlloc(n * sizeof(char));
+    for (i = 0; i < n; i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->mask[i] = 0.0;
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial2D* psDPolynomial2DAlloc(int nX, int nY)
+{
+    int x = 0;
+    int y = 0;
+    psDPolynomial2D* newPoly = NULL;
+
+    newPoly = (psDPolynomial2D* ) psAlloc(sizeof(psDPolynomial2D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial2DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->coeffErr = (double **)psAlloc(nX * sizeof(double *));
+    newPoly->mask = (char **)psAlloc(nX * sizeof(char *));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->coeffErr[x] = (double *)psAlloc(nY * sizeof(double));
+        newPoly->mask[x] = (char *)psAlloc(nY * sizeof(char));
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->mask[x][y] = 0;
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial3D* psDPolynomial3DAlloc(int nX, int nY, int nZ)
+{
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial3D* newPoly = NULL;
+
+    newPoly = (psDPolynomial3D* ) psAlloc(sizeof(psDPolynomial3D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial3DFree);
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->coeffErr = (double ***)psAlloc(nX * sizeof(double **));
+    newPoly->mask = (char ***)psAlloc(nX * sizeof(char **));
+    for (x = 0; x < nX; x++) {
+        newPoly->coeff[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->coeffErr[x] = (double **)psAlloc(nY * sizeof(double *));
+        newPoly->mask[x] = (char **)psAlloc(nY * sizeof(char *));
+        for (y = 0; y < nY; y++) {
+            newPoly->coeff[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->coeffErr[x][y] = (double *)psAlloc(nZ * sizeof(double));
+            newPoly->mask[x][y] = (char *)psAlloc(nZ * sizeof(char));
+        }
+    }
+    for (x = 0; x < nX; x++) {
+        for (y = 0; y < nY; y++) {
+            for (z = 0; z < nZ; z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->mask[x][y][z] = 0;
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+psDPolynomial4D* psDPolynomial4DAlloc(int nW, int nX, int nY, int nZ)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+    int z = 0;
+    psDPolynomial4D* newPoly = NULL;
+
+    newPoly = (psDPolynomial4D* ) psAlloc(sizeof(psDPolynomial4D));
+    p_psMemSetDeallocator(newPoly, (psFreeFcn) dPolynomial4DFree);
+    newPoly->nW = nW;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->coeffErr = (double ****)psAlloc(nW * sizeof(double ***));
+    newPoly->mask = (char ****)psAlloc(nW * sizeof(char ***));
+    for (w = 0; w < nW; w++) {
+        newPoly->coeff[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->coeffErr[w] = (double ***)psAlloc(nX * sizeof(double **));
+        newPoly->mask[w] = (char ***)psAlloc(nX * sizeof(char **));
+        for (x = 0; x < nX; x++) {
+            newPoly->coeff[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->coeffErr[w][x] = (double **)psAlloc(nY * sizeof(double *));
+            newPoly->mask[w][x] = (char **)psAlloc(nY * sizeof(char *));
+            for (y = 0; y < nY; y++) {
+                newPoly->coeff[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->coeffErr[w][x][y] = (double *)psAlloc(nZ * sizeof(double));
+                newPoly->mask[w][x][y] = (char *)psAlloc(nZ * sizeof(char));
+            }
+        }
+    }
+    for (w = 0; w < nW; w++) {
+        for (x = 0; x < nX; x++) {
+            for (y = 0; y < nY; y++) {
+                for (z = 0; z < nZ; z++) {
+                    newPoly->coeff[w][x][y][z] = 0.0;
+                    newPoly->coeffErr[w][x][y][z] = 0.0;
+                    newPoly->mask[w][x][y][z] = 0;
+                }
+            }
+        }
+    }
+
+    return (newPoly);
+}
+
+static void dPolynomial1DFree(psDPolynomial1D* myPoly)
+{
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial2DFree(psDPolynomial2D* myPoly)
+{
+    int x = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial3DFree(psDPolynomial3D* myPoly)
+{
+    int x = 0;
+    int y = 0;
+
+    for (x = 0; x < myPoly->nX; x++) {
+        for (y = 0; y < myPoly->nY; y++) {
+            psFree(myPoly->coeff[x][y]);
+            psFree(myPoly->coeffErr[x][y]);
+            psFree(myPoly->mask[x][y]);
+        }
+        psFree(myPoly->coeff[x]);
+        psFree(myPoly->coeffErr[x]);
+        psFree(myPoly->mask[x]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+static void dPolynomial4DFree(psDPolynomial4D* myPoly)
+{
+    int w = 0;
+    int x = 0;
+    int y = 0;
+
+    for (w = 0; w < myPoly->nW; w++) {
+        for (x = 0; x < myPoly->nX; x++) {
+            for (y = 0; y < myPoly->nY; y++) {
+                psFree(myPoly->coeff[w][x][y]);
+                psFree(myPoly->coeffErr[w][x][y]);
+                psFree(myPoly->mask[w][x][y]);
+            }
+            psFree(myPoly->coeff[w][x]);
+            psFree(myPoly->coeffErr[w][x]);
+            psFree(myPoly->mask[w][x]);
+        }
+        psFree(myPoly->coeff[w]);
+        psFree(myPoly->coeffErr[w]);
+        psFree(myPoly->mask[w]);
+    }
+
+    psFree(myPoly->coeff);
+    psFree(myPoly->coeffErr);
+    psFree(myPoly->mask);
+}
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ *****************************************************************************/
+double psDPolynomial1DEval(double x, const psDPolynomial1D* myPoly)
+{
+    int loop_x = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+
+    // NOTE: Do we want to flag this case?
+    if (myPoly->n == 0) {
+        return (1.0);
+    }
+
+    for (loop_x = 0; loop_x < myPoly->n; loop_x++) {
+        polySum += xSum * myPoly->coeff[loop_x];
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial2DEval(double x, double y, const psDPolynomial2D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            polySum += ySum * myPoly->coeff[loop_x][loop_y];
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial3DEval(double x, double y, double z, const psDPolynomial3D* myPoly)
+{
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                polySum += zSum * myPoly->coeff[loop_x][loop_y][loop_z];
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (polySum);
+}
+
+double psDPolynomial4DEval(double w, double x, double y, double z, const psDPolynomial4D* myPoly)
+{
+    int loop_w = 0;
+    int loop_x = 0;
+    int loop_y = 0;
+    int loop_z = 0;
+    double polySum = 0.0;
+    double wSum = 1.0;
+    double xSum = 1.0;
+    double ySum = 1.0;
+    double zSum = 1.0;
+
+    for (loop_w = 0; loop_w < myPoly->nW; loop_w++) {
+        xSum = wSum;
+        for (loop_x = 0; loop_x < myPoly->nX; loop_x++) {
+            ySum = xSum;
+            for (loop_y = 0; loop_y < myPoly->nY; loop_y++) {
+                zSum = ySum;
+                for (loop_z = 0; loop_z < myPoly->nZ; loop_z++) {
+                    polySum += zSum * myPoly->coeff[loop_w][loop_x][loop_y][loop_z];
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+        wSum *= w;
+    }
+
+    return (polySum);
+}
Index: /tags/rel2_1/psLib/src/math/psSpline.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psSpline.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psSpline.h	(revision 1553)
@@ -0,0 +1,318 @@
+
+/** @file psFunctions.h
+*  \brief Standard Mathematical Functions.
+*  \ingroup Stats
+*
+*  This file will hold the prototypes for procedures which allocate, free,
+*  and evaluate various polynomials.  Those polynomial structures are also
+*  defined here.
+*
+*  @ingroup Stats
+*
+*  @author Someone at IfA
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-11 02:35:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#if !defined(PS_FUNCTIONS_H)
+#define PS_FUNCTIONS_H
+
+#include <stdbool.h>
+
+#include "psVector.h"
+
+/** \addtogroup Stats
+ *  \{
+ */
+
+/** Evaluate a non-normalized Gaussian with the given mean and sigma at the
+ *  given coordianate.  
+ *
+ *  Note that this is not a Gaussian deviate.  The evaluated Gaussian is: 
+ *        \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f] 
+ *
+ *  @return float      value on the gaussian curve given the input parameters
+ */
+float psGaussian(
+    float x,                           ///< Value at which to evaluate
+    float mean,                        ///< Mean for the Gaussian
+    float stddev,                      ///< Standard deviation for the Gaussian
+    bool normal                        ///< Indicates whether result should be normalized
+);
+
+/** Produce a vector of random numbers from a Gaussian distribution with
+ *  the specified mean and sigma 
+ *  
+ *  @return psVector*    vector of random numbers
+ *  
+ */
+psVector* psGaussianDev(
+    float mean,                        ///< The mean of the Gaussian
+    float sigma,                       ///< The sigma of the Gaussian
+    int Npts                           ///< The size of the vector
+);
+
+/** One-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    float *coeff;                      ///< Coefficients
+    float *coeffErr;                   ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psPolynomial1D;
+
+/** Two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    float **coeff;                     ///< Coefficients
+    float **coeffErr;                  ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psPolynomial2D;
+
+/** Three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ***coeff;                    ///< Coefficients
+    float ***coeffErr;                 ///< Error in coefficients
+    char ***mask;                      ///< Coefficients mask
+}
+psPolynomial3D;
+
+/** Four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    float ****coeff;                   ///< Coefficients
+    float ****coeffErr;                ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psPolynomial4D;
+
+
+/** Allocates a psPolynomial1D structure with n terms
+ *
+ *  @return  psPolynomial1D*    new 1-D polynomial struct
+ */
+psPolynomial1D* psPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new 2-D polynomial struct
+ */
+psPolynomial2D* psPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new 3-D polynomial struct
+ */
+psPolynomial3D* psPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new 4-D polynomial struct
+ */
+psPolynomial4D* psPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial1DEval(
+    float x,                           ///< location at which to evaluate
+    const psPolynomial1D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial2DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    const psPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial3DEval(
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial3D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+float psPolynomial4DEval(
+    float w,                           ///< w location at which to evaluate
+    float x,                           ///< x location at which to evaluate
+    float y,                           ///< y location at which to evaluate
+    float z,                           ///< z location at which to evaluate
+    const psPolynomial4D* myPoly       ///< Coefficients for the polynomial
+);
+
+/*****************************************************************************/
+
+/* Double-precision polynomials, mainly for use in astrometry */
+
+/** Double-precision one-dimensional polynomial */
+typedef struct
+{
+    int n;                             ///< Number of terms
+    double *coeff;                     ///< Coefficients
+    double *coeffErr;                  ///< Error in coefficients
+    char *mask;                        ///< Coefficient mask
+}
+psDPolynomial1D;
+
+/** Double-precision two-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    double **coeff;                    ///< Coefficients
+    double **coeffErr;                 ///< Error in coefficients
+    char **mask;                       ///< Coefficients mask
+}
+psDPolynomial2D;
+
+/** Double-precision three-dimensional polynomial */
+typedef struct
+{
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ***coeff;                   ///< Coefficients
+    double ***coeffErr;                ///< Error in coefficients
+    char ***mask;                      ///< Coefficient mask
+}
+psDPolynomial3D;
+
+/** Double-precision four-dimensional polynomial */
+typedef struct
+{
+    int nW;                            ///< Number of terms in w
+    int nX;                            ///< Number of terms in x
+    int nY;                            ///< Number of terms in y
+    int nZ;                            ///< Number of terms in z
+    double ****coeff;                  ///< Coefficients
+    double ****coeffErr;               ///< Error in coefficients
+    char ****mask;                     ///< Coefficients mask
+}
+psDPolynomial4D;
+
+/** Allocates a double-precision 1-D polynomial structure with n terms
+ *
+ *  @return  psPolynomial1D*    new double-precision 1-D polynomial struct
+ */
+psDPolynomial1D* psDPolynomial1DAlloc(
+    int n                              ///< Number of terms
+);
+
+/** Allocates a double-precision 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new double-precision 2-D polynomial struct
+ */
+psDPolynomial2D* psDPolynomial2DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY                             ///< Number of terms in y
+);
+
+/** Allocates a double-precision 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new double-precision 3-D polynomial struct
+ */
+psDPolynomial3D* psDPolynomial3DAlloc(
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Allocates a double-precision 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new double-precision 4-D polynomial struct
+ */
+psDPolynomial4D* psDPolynomial4DAlloc(
+    int nW,                            ///< Number of terms in w
+    int nX,                            ///< Number of terms in x
+    int nY,                            ///< Number of terms in y
+    int nZ                             ///< Number of terms in z
+);
+
+/** Evaluates a double-precision 1-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial1DEval(
+    double x,                          ///< Value at which to evaluate
+    const psDPolynomial1D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 2-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial2DEval(
+    double x,                           ///< Value x at which to evaluate
+    double y,                           ///< Value y at which to evaluate
+    const psDPolynomial2D* myPoly       ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 3-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial3DEval(
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial3D* myPoly      ///< Coefficients for the polynomial
+);
+
+/** Evaluates a double-precision 4-D polynomial at specific coordinates.
+ *
+ *  @return float    result of polynomial at given location
+ */
+double psDPolynomial4DEval(
+    double w,                          ///< Value w at which to evaluate
+    double x,                          ///< Value x at which to evaluate
+    double y,                          ///< Value y at which to evaluate
+    double z,                          ///< Value z at which to evaluate
+    const psDPolynomial4D* myPoly      ///< Coefficients for the polynomial
+);
+
+/* \} */// End of MathGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/math/psStats.c
===================================================================
--- /tags/rel2_1/psLib/src/math/psStats.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psStats.c	(revision 1553)
@@ -0,0 +1,1888 @@
+
+/** @file  psStats.c
+ *  \brief basic statistical operations
+ *  @ingroup Stats
+ *
+ *  This file will hold the definition of the histogram and stats data
+ *  structures.  It also contains prototypes for procedures which operate
+ *  on those data structures.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+/*****************************************************************************/
+
+/* INCLUDE FILES                                                             */
+
+/*****************************************************************************/
+#include "psMemory.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psStats.h"
+#include "psMinimize.h"
+#include "psFunctions.h"
+
+/*****************************************************************************/
+
+/* DEFINE STATEMENTS                                                         */
+
+/*****************************************************************************/
+// will use robust statistical methods.
+#define GAUSS_WIDTH 20                     // The width of the Gaussian or boxcar smoothing.
+#define CLIPPED_NUM_ITER_LB 1
+#define CLIPPED_NUM_ITER_UB 10
+#define CLIPPED_SIGMA_LB 1.0
+#define CLIPPED_SIGMA_UB 10.0
+#define true 1
+#define false 0
+#define MY_MAX_FLOAT HUGE
+#define MAX_ITERATIONS 10
+
+void p_psVectorRobustStats(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats);
+
+/** Preprocessor macro to generate error on an incorrect type */
+#define PS_CHECK_VECTOR_TYPE(NAME, TYPE) \
+if (NAME->type.type != TYPE) { \
+    psError(__func__,"Invalid operation: %s has incorrect type.", #NAME); \
+}
+
+/** Preprocessor macro to generate error on a NULL vector */
+#define PS_CHECK_NULL_VECTOR(NAME) \
+if (NAME == NULL || NAME->data.V == NULL) { \
+    psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME); \
+}
+
+/** Preprocessor macro to generate error for zero length vector */
+#define PS_CHECK_EMPTY_VECTOR(NAME) \
+if (NAME->n < 1) { \
+    psError(__func__,"Invalid operation: %s has zero n value.", #NAME); \
+}
+
+/** Preprocessor macro to generate error on differing size vectors */
+#define PS_CHECK_VECTOR_SIZE_EQUAL(VEC1, VEC2) \
+if (VEC1->n != VEC2->n) { \
+    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
+}
+
+#define PS_PRINT_VECTOR(NAME) \
+for (int my_i=0;my_i<NAME->n;my_i++) { \
+    printf("%s->data.F32[%d] is %f\n", #NAME, my_i, NAME->data.F32[my_i]); \
+} \
+printf("\n"); \
+
+
+/*****************************************************************************/
+
+/* TYPE DEFINITIONS                                                          */
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+
+/* GLOBAL VARIABLES                                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FILE STATIC VARIABLES                                                     */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+
+/*****************************************************************************/
+
+bool p_psGetStatValue(const psStats* stats, double *value)
+{
+
+    switch (stats->options & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE | PS_STAT_ROBUST_FOR_SAMPLE)) {
+    case PS_STAT_SAMPLE_MEAN:
+        *value = stats->sampleMean;
+        return true;
+
+    case PS_STAT_SAMPLE_MEDIAN:
+        *value = stats->sampleMedian;
+        return true;
+
+    case PS_STAT_SAMPLE_STDEV:
+        *value = stats->sampleStdev;
+        return true;
+
+    case PS_STAT_ROBUST_MEAN:
+        *value = stats->robustMean;
+        return true;
+
+    case PS_STAT_ROBUST_MEDIAN:
+        *value = stats->robustMedian;
+        return true;
+
+    case PS_STAT_ROBUST_MODE:
+        *value = stats->robustMode;
+        return true;
+
+    case PS_STAT_ROBUST_STDEV:
+        *value = stats->robustStdev;
+        return true;
+
+    case PS_STAT_CLIPPED_MEAN:
+        *value = stats->clippedMean;
+        return true;
+
+    case PS_STAT_CLIPPED_STDEV:
+        *value = stats->clippedStdev;
+        return true;
+
+    case PS_STAT_MAX:
+        *value = stats->max;
+        return true;
+
+    case PS_STAT_MIN:
+        *value = stats->min;
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+/*****************************************************************************
+p_psVectorPrint(myVector, maskVector, maskVal, stats): a private internal
+function that simply prints a vector to STDOUT.  Used primarily for
+debugging.
+ *****************************************************************************/
+
+void p_psVectorPrint(psVector* myVector, psVector* maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable.
+
+    for (i = 0; i < myVector->n; i++) {
+        if (maskVector != NULL)
+            printf("Element %d is %f (mask is %d)\n", i, myVector->data.F32[i], maskVector->data.U8[i]);
+        else
+            printf("Element %d is %f\n", i, myVector->data.F32[i]);
+    }
+}
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+    MISC PRIVATE STATISTICAL FUNCTIONS
+ 
+    NOTE: it is assumed that any call to these statistical functions will
+    have been preceded by a call to the psVectorStats() function.  Various
+    sanity tests will only be performed in psVectorStats().
+        Is the mask vector the same length as the data vector?
+        Is the mask vector of type PS_TYPE_U8?
+        Is the stats data structure NULL?
+        Is the in data structure NULL?
+        Is the in data structure of type PS_TYPE_F32?
+ ******************************************************************************
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+p_psVectorSampleMean(myVector, maskVector, maskVal, stats): calculates the
+mean of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ASSUMPTION: the mean is always calculated exactly.  Robust means are never
+calculated in this routine.
+ *****************************************************************************/
+
+void p_psVectorSampleMean(const psVector* restrict myVector,
+                          const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float mean = 0.0;           // The mean
+    int count = 0;              // # of points in this mean?
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // If PS_STAT_USE_RANGE is requested, then we enter a slightly different
+    // loop.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                // Check if the data is with the specified range
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    mean += myVector->data.F32[i];
+                    count++;
+                }
+            }
+            mean /= (float)count;
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                mean += myVector->data.F32[i];
+            }
+            mean /= (float)myVector->n;
+        }
+    }
+
+    stats->sampleMean = mean;
+}
+
+/******************************************************************************
+p_psVectorSampleMax(myVector, maskVector, maskVal, stats): calculates the
+max of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorMax(const psVector* restrict myVector,
+                   const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float max = -MY_MAX_FLOAT;  // The calculated maximum
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // If PS_STAT_USE_RANGE is requested, then we enter a different loop.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if ((myVector->data.F32[i] > max) &&
+                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                        max = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((myVector->data.F32[i] > max) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    max = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if (myVector->data.F32[i] > max) {
+                        max = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if (myVector->data.F32[i] > max) {
+                    max = myVector->data.F32[i];
+                }
+            }
+        }
+    }
+
+    stats->max = max;
+}
+
+/******************************************************************************
+p_psVectorSampleMin(myVector, maskVector, maskVal, stats): calculates the
+minimum of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorMin(const psVector* restrict myVector,
+                   const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    float min = MY_MAX_FLOAT;   // The calculated maximum
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if ((myVector->data.F32[i] < min) &&
+                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                        min = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((myVector->data.F32[i] < min) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    min = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    if (myVector->data.F32[i] < min) {
+                        min = myVector->data.F32[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if (myVector->data.F32[i] < min) {
+                    min = myVector->data.F32[i];
+                }
+            }
+        }
+    }
+
+    stats->min = min;
+}
+
+/******************************************************************************
+p_psVectorNValues(myVector, maskVector, maskVal, stats): calculates the
+number of non-masked pixels in the vector that fall within the min/max
+range, if given.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+int p_psVectorNValues(const psVector* restrict myVector,
+                      const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int numData = 0;            // The number of data points
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    numData++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    numData++;
+                }
+            }
+        }
+    } else {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    numData++;
+                }
+            }
+        } else {
+            numData = myVector->n;
+        }
+    }
+    return (numData);
+}
+
+/******************************************************************************
+p_psVectorSampleMedian(myVector, maskVector, maskVal, stats): calculates the
+median of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorSampleMedian(const psVector* restrict myVector,
+                            const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psVector* unsortedVector = NULL;    // Temporary vector
+    psVector* sortedVector = NULL;      // Temporary vector
+    int i = 0;                  // Loop index variable
+    int count = 0;              // # of points in this mean?
+    int nValues = 0;            // # of points in vector
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // Determine if the number of data points exceed a threshold which will
+    // cause to generate robust stats, as opposed to exact stats.
+    // XXX: This code is no longer used.  We now calculate the median exactly
+    // regardless of the vector size.
+    /*
+     * if (myVector->n > stats->sampleLimit) { psAbort(__func__, "Robust Statistic Algorithms have not yet
+     * been defined or implemented.");
+     * 
+     * // Calculate the robust quartiles. stats2 = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
+     * p_psVectorRobustStats(myVector, maskVector, maskVal, stats2);
+     * 
+     * // Store the robust quartiles into the sample quartile members. stats->sampleMedian =
+     * stats2->robustMedian;
+     * 
+     * // Free temporary data buffers. psFree(stats2);
+     * 
+     * // Set the PS_STAT_ROBUST_FOR_SAMPLE bit in the stats structure. stats->options = stats->options |
+     * PS_STAT_ROBUST_FOR_SAMPLE;
+     * 
+     * return; } */
+
+    // Determine how many data points fit inside this min/max range
+    // and are not masked, IF the maskVector is not NULL>
+    nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats);
+
+    // Allocate temporary vectors for the data.
+    unsortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    unsortedVector->n = unsortedVector->nalloc;
+
+    sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    sortedVector->n = sortedVector->nalloc;
+
+    // Determine if we must only use data points within a min/max range.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+
+        // Store all non-masked data points within the min/max range
+        // into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = maskVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        // Store all non-masked data points into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                unsortedVector->data.F32[i] = myVector->data.F32[i];
+            }
+        }
+    }
+    // Sort the temporary vectors.
+    psVectorSort(sortedVector, unsortedVector);
+
+    // Calculate the median exactly.
+    // XXX: Is this the correct action?
+    if (0 == (nValues % 2)) {
+        stats->sampleMedian = 0.5 * (sortedVector->data.F32[(nValues / 2) - 1] +
+                                     sortedVector->data.F32[nValues / 2]);
+    } else {
+        stats->sampleMedian = sortedVector->data.F32[nValues / 2];
+    }
+
+    // Free the temporary data structures.
+    psFree(unsortedVector);
+    psFree(sortedVector);
+}
+
+/******************************************************************************
+    This routine smoothes the data in the input robustHistogram with a
+    Gaussian of width sigma.
+ 
+    XXX: Must consult with IfA on the proper values for the Gaussian
+    smoothing.  Currently, the Gaussian coefficients are such that only
+    the center coefficient is non-zero.  This is because "e" is being
+    raised to a very large negative number for all points except the
+    center point.
+ 
+    XXX: use a static variable for gaussianCoefs[] and compute them once.
+ *****************************************************************************/
+psVector* p_psVectorsmoothHistGaussian(psHistogram* robustHistogram, float sigma)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float denom = 0.0;          // Temporary variable
+    float expo = 0.0;           // Temporary variable
+    float gaussianCoefs[1 + (2 * GAUSS_WIDTH)]; // The Gaussian Coefficients
+    psVector* smooth = psVectorAlloc(robustHistogram->nums->n, PS_TYPE_F32);
+
+    for (i = 0; i < (1 + (2 * GAUSS_WIDTH)); i++) {
+        if (fabs(sigma) >= FLT_EPSILON) {
+            // If sigma does not equal zero, then we use Gaussian smoothing.
+            #ifdef  DARWIN
+            denom = (float)sqrt(2.0 * M_PI * sigma * sigma);
+            #else
+
+            denom = sqrtf(2.0 * M_PI * sigma * sigma);
+            #endif
+
+            expo = -(float)((i - GAUSS_WIDTH) * (i - GAUSS_WIDTH));
+            expo /= (2.0 * sigma * sigma);
+            gaussianCoefs[i] = exp(expo / denom);
+
+            // NOTE: Gaussian smoothing just isn't working with low sigma
+            // values.  The problem is that the Gaussian coefficients are
+            // all zero, except for the middle coefficient, which is exactly
+            // one.  Therefore, I'm using boxcar smoothing.
+            gaussianCoefs[i] = 1.0 / (1.0 + (2.0 * (float)GAUSS_WIDTH));
+            // printf("gaussianCoefs[%d] is %f\n", i, gaussianCoefs[i]);
+        } else {
+            /* If sigma equals zero (all pixels have the same value) the above code will divide by zero.
+             * Therefore, we don't need to smooth the data. */
+            for (i = 0; i < robustHistogram->nums->n; i++) {
+                smooth->data.F32[i] = (float)robustHistogram->nums->data.S32[i];
+            }
+            return (smooth);
+        }
+    }
+
+    // Perform the actual smoothing.
+    for (i = 0; i < robustHistogram->nums->n; i++) {
+        smooth->data.F32[i] = 0.0;
+        for (j = -GAUSS_WIDTH; j <= +GAUSS_WIDTH; j++) {
+            if (((j + i) >= 0) && ((j + i) < smooth->n)) {
+                smooth->data.F32[i] += (gaussianCoefs[j + GAUSS_WIDTH] *
+                                        (float)robustHistogram->nums->data.S32[j + i]);
+            }
+        }
+    }
+    return (smooth);
+}
+
+/******************************************************************************
+p_psVectorSampleQuartiles(myVector, maskVector, maskVal, stats): calculates
+the upper and/or lower quartiles of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorSampleQuartiles(const psVector* restrict myVector,
+                               const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psVector* unsortedVector = NULL;    // Temporary vector
+    psVector* sortedVector = NULL;      // Temporary vector
+    int i = 0;                  // Loop index variable
+    int count = 0;              // # of points in this mean?
+    int nValues = 0;            // # data points
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // Determine how many data points fit inside this min/max range
+    // and are not maxed, IF the maskVector is not NULL>
+    nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats);
+
+    // Allocate temporary vectors for the data.
+    unsortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    unsortedVector->n = unsortedVector->nalloc;
+    sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);
+    sortedVector->n = sortedVector->nalloc;
+
+    // Determine if we must only use data points within a min/max range.
+    if (stats->options & PS_STAT_USE_RANGE) {
+        rangeMin = stats->min;
+        rangeMax = stats->max;
+        // Store all non-masked data points within the min/max range
+        // into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        }
+    } else {
+        // Store all non-masked data points into the temporary vectors.
+        count = 0;
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    unsortedVector->data.F32[count++] = myVector->data.F32[i];
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                unsortedVector->data.F32[i] = myVector->data.F32[i];
+            }
+        }
+    }
+
+    // Sort the temporary vectors.
+    psVectorSort(sortedVector, unsortedVector);
+
+    // Calculate the quartile points exactly.
+    stats->sampleUQ = sortedVector->data.F32[3 * (nValues / 4)];
+    stats->sampleLQ = sortedVector->data.F32[nValues / 4];
+
+    // Free the temporary data structures.
+    psFree(unsortedVector);
+    psFree(sortedVector);
+}
+
+/******************************************************************************
+p_psVectorSampleStdev(myVector, maskVector, maskVal, stats): calculates the
+stdev of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ 
+ *****************************************************************************/
+void p_psVectorSampleStdev(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int countInt = 0;           // # of data points being used
+    float countFloat = 0.0;     // # of data points being used
+    float mean = 0.0;           // The mean
+    float diff = 0.0;           // Used in calculating stdev
+    float sumSquares = 0.0;     // temporary variable
+    float sumDiffs = 0.0;       // temporary variable
+    float rangeMin = 0.0;       // Exclude data below this
+    float rangeMax = 0.0;       // Exclude date above this
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call p_psVectorSampleMean()
+    if (0 != isnan(stats->sampleMean)) {
+        p_psVectorSampleMean(myVector, maskVector, maskVal, stats);
+    }
+    mean = stats->sampleMean;
+
+    if (stats->options & PS_STAT_USE_RANGE) {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i]) &&
+                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+            countInt = myVector->n;
+        }
+    } else {
+        if (maskVector != NULL) {
+            for (i = 0; i < myVector->n; i++) {
+                if (!(maskVal & maskVector->data.U8[i])) {
+                    diff = myVector->data.F32[i] - mean;
+                    sumSquares += (diff * diff);
+                    sumDiffs += diff;
+                    countInt++;
+                }
+            }
+        } else {
+            for (i = 0; i < myVector->n; i++) {
+                diff = myVector->data.F32[i] - mean;
+                sumSquares += (diff * diff);
+                sumDiffs += diff;
+                countInt++;
+            }
+            countInt = myVector->n;
+        }
+    }
+    countFloat = (float)countInt;
+
+    #ifdef DARWIN
+
+    stats->sampleStdev = (float)sqrt((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+    #else
+
+    stats->sampleStdev = sqrtf((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+    #endif
+}
+
+/******************************************************************************
+p_psVectorClippedStats(myVector, maskVector, maskVal, stats): calculates the
+clipped stats (mean or stdev) of the input vector.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+ *****************************************************************************/
+void p_psVectorClippedStats(const psVector* restrict myVector,
+                            const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float clippedMean = 0.0;    // self-explanatory
+    float clippedStdev = 0.0;   // self-explanatory
+    float oldStanMean = 0.0;    // Temporary variable
+    float oldStanStdev = 0.0;   // Temporary variable
+    psVector* tmpMask = NULL;   // Temporary vector
+
+    // Endure that stats->clipIter is within the proper range.
+    if (!((CLIPPED_NUM_ITER_LB <= stats->clipIter) && (stats->clipIter <= CLIPPED_NUM_ITER_UB))) {
+        psAbort(__func__, "Unallowed value for clipIter (%d).\n", stats->clipIter);
+    }
+    // Endure that stats->clipSigma is within the proper range.
+    if (!((CLIPPED_SIGMA_LB <= stats->clipSigma) && (stats->clipSigma <= CLIPPED_SIGMA_UB))) {
+        psAbort(__func__, "Unallowed value for clipSigma (%f).\n", stats->clipSigma);
+    }
+    // We allocate a temporary mask vector since during the iterative
+    // steps that follow, we will be masking off additional data points.
+    // However, we do no want to modify the original mask vector.
+    tmpMask = psVectorAlloc(myVector->n, PS_TYPE_U8);
+    tmpMask->n = myVector->n;
+
+    // If we were called with a mask vector, then initialize the temporary
+    // mask vector with those values.
+    if (maskVector != NULL) {
+        for (i = 0; i < tmpMask->n; i++) {
+            tmpMask->data.U8[i] = maskVector->data.U8[i];
+        }
+    }
+    // 1. Compute the sample median.
+    // NOTE: This seems odd.  Verify with IfA that we want to calculate the
+    // median here, not the mean.
+    p_psVectorSampleMedian(myVector, maskVector, maskVal, stats);
+
+    // 2. Compute the sample standard deviation.
+    p_psVectorSampleStdev(myVector, maskVector, maskVal, stats);
+
+    // 3. Use the sample median as the first estimator of the mean X.
+    clippedMean = stats->sampleMean;
+
+    // 4. Use the sample stdev as the first estimator of the mean stdev.
+    clippedStdev = stats->sampleStdev;
+
+    // Must save the old sampleMean and sampleStdev since the following code
+    // block overwrites them.
+    oldStanMean = stats->sampleMean;
+    oldStanStdev = stats->sampleStdev;
+
+    // 5. Repeat N times:
+    for (i = 0; i < stats->clipIter; i++) {
+        for (j = 0; j < myVector->n; j++) {
+            // a) Exclude all values x_i for which |x_i - x| > K * stdev
+            if (fabs(myVector->data.F32[j] - clippedMean) > (stats->clipSigma * clippedStdev)) {
+                tmpMask->data.U8[i] = 0xff;
+            }
+            // b) compute new mean and stdev
+            p_psVectorSampleMedian(myVector, tmpMask, maskVal, stats);
+            p_psVectorSampleStdev(myVector, tmpMask, maskVal, stats);
+
+            // c) Use the new mean for x
+            clippedMean = stats->sampleMean;
+
+            // d) Use the new stdev for stdev
+            clippedStdev = stats->sampleStdev;
+        }
+
+    }
+    stats->sampleMean = oldStanMean;
+    stats->sampleStdev = oldStanStdev;
+
+    // 7. The last calcuated value of x is the cliped mean.
+    if (stats->options & PS_STAT_CLIPPED_MEAN) {
+        stats->clippedMean = clippedMean;
+    }
+    // 8. The last calcuated value of stdev is the cliped stdev.
+    if (stats->options & PS_STAT_CLIPPED_STDEV) {
+        stats->clippedStdev = clippedStdev;
+    }
+
+    psFree(tmpMask);
+}
+
+/*****************************************************************************
+p_psNormalizeVector(myData): this is a private function which normalizes the
+elements of a vector to a range between 0.0 and 1.0.
+ *****************************************************************************/
+void p_psNormalizeVector(psVector* myData)
+{
+    float min = (float)HUGE;
+    float max = (float)-HUGE;
+    float range = 0.0;
+    int i = 0;
+
+    for (i = 0; i < myData->n; i++) {
+        if (myData->data.F32[i] < min) {
+            min = myData->data.F32[i];
+        }
+        if (myData->data.F32[i] > max) {
+            max = myData->data.F32[i];
+        }
+    }
+
+    range = max - min;
+    for (i = 0; i < myData->n; i++) {
+        myData->data.F32[i] = (myData->data.F32[i] - min) / range;
+    }
+}
+
+/*****************************************************************************
+p_psGaussian(myData, myParams): an internal function, used by robust stats,
+intended to compute the Gaussian with a specified sigma/mean, at the
+specified data point.
+ *****************************************************************************/
+float p_psGaussian(const psVector* restrict myData, const psVector* restrict myParams)
+{
+    float x = myData->data.F32[0];
+    float mean = myParams->data.F32[0];
+    float stdev = myParams->data.F32[1];
+    float tmp = exp(-((x - mean) * (x - mean)) / (2.0 * stdev * stdev));
+
+    tmp /= ((float)sqrt(2.0 * M_PI * (stdev * stdev)));
+
+    // printf("p_psGaussian((%.2f), %.2f, %.2f) is %.2f\n", x, mean, stdev, tmp);
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psGaussianDeriv(myData, myParams, whichParam): an internal function, which
+calculates the specified partial derivative of the above Gaussian function.
+ *****************************************************************************/
+float p_psGaussianDeriv(const psVector* restrict myData, const psVector* restrict myParams, int whichParam)
+{
+    float x = myData->data.F32[0];
+    float mean = myParams->data.F32[0];
+    float stdev = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParam == 0) {
+        // Return the derivative w.r.t. the mean.
+        tmp = (x - mean) * p_psGaussian(myData, myParams);
+        tmp /= (stdev * stdev);
+    } else if (whichParam == 1) {
+        // Return the derivative w.r.t. the stdev.
+        tmp = (x - mean) * (x - mean) * p_psGaussian(myData, myParams);
+        tmp /= (stdev * stdev * stdev);
+    }
+    printf("p_psGaussianDeriv((%.2f), %.2f, %.2f, (%d)) is %.2f\n", x, mean, stdev, whichParam, tmp);
+
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psQuadratic(myData, myParams): an internal function, used by robust stats,
+intended to compute a quadratic, with the specified parameters, at the
+specified data point.
+ *****************************************************************************/
+float p_psQuadratic(const psVector* restrict myParams, const psVector* restrict myCoords)
+{
+    float x = myCoords->data.F32[0];
+    float A = myParams->data.F32[0];
+    float B = myParams->data.F32[1];
+    float C = myParams->data.F32[2];
+    float tmp = 0.0;
+
+    tmp = (A * x * x) + (B * x) + C;
+    return (tmp);
+}
+
+/*****************************************************************************
+p_psQuadraticDeriv(myData, myParams, whichParam): an internal function, which
+calculates the specified partial derivative of the above quadratic function.
+ *****************************************************************************/
+float p_psQuadraticDeriv(const psVector* restrict myParams,
+                         const psVector* restrict myCoords, int whichParamDeriv)
+{
+    float x = myCoords->data.F32[0];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = x * x;
+    } else if (whichParamDeriv == 1) {
+        tmp = x;
+    } else if (whichParamDeriv == 2) {
+        tmp = 1.0;
+    }
+
+    return (tmp);
+}
+
+/******************************************************************************
+p_ps1DPolyMedian(myPoly, rangeLow, rangeHigh, midpoint): This routine takes
+as input a 1-D polynomial of arbitrary order (though we are using 2nd-order
+polynomials here) and a range of x-values for which it is defined:
+[rangeLow, rangeHigh].  It determines the x-value of that polynomial such
+that f(x) == midpoint.  This functions uses a binary-search algorithm on the
+range and assumes that the polynomial is monotonically increasing or
+decreasing within that range.
+ *****************************************************************************/
+float p_ps1DPolyMedian(psPolynomial1D* myPoly, float rangeLow, float rangeHigh, float getThisValue)
+{
+    int numIterations = 0;
+    float midpoint = 0.0;
+    float oldMidpoint = 1.0;
+    float f = 0.0;
+
+    // printf("p_ps1DPolyMedian(%f, %f, %f) \n", rangeLow, rangeHigh, getThisValue);
+
+    while (numIterations < MAX_ITERATIONS) {
+        midpoint = (rangeHigh + rangeLow) / 2.0;
+        if (fabs(midpoint - oldMidpoint) <= FLT_EPSILON) {
+            return (midpoint);
+        }
+        oldMidpoint = midpoint;
+
+        f = psPolynomial1DEval(midpoint, myPoly);
+        // printf("p_ps1DPolyMedian() iteration %d.  f(%f) is %f\n", numIterations, midpoint, f);
+        if (fabs(f - getThisValue) <= FLT_EPSILON) {
+            return (midpoint);
+        }
+
+        if (f > getThisValue) {
+            rangeHigh = midpoint;
+        } else {
+            rangeLow = midpoint;
+        }
+        numIterations++;
+    }
+    return (midpoint);
+}
+
+/******************************************************************************
+p_psFitQuadratic(robustHistogram. cumulativeSums, binNum, fitFloat): given
+the specified histogram, with the specified pre-calculated cumulativeSums,
+this routine fits a quadratic f(x) to the 3 bins surrounding bin "binNum",
+and then finds the point x such that f(x) == fitFloat.
+ 
+XXX: This function is currently not being used.
+ *****************************************************************************/
+float p_psFitQuadratic(psHistogram* histogram, psVector* cumulativeSums, int binNum, float fitFloat)
+{
+    psVector* x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* y = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* yErr = psVectorAlloc(3, PS_TYPE_F64);
+    psPolynomial1D* myPoly = psPolynomial1DAlloc(2);
+
+    if ((binNum > 0) && (binNum < (histogram->nums->n + 1))) {
+        x->data.F64[0] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum - 1] + histogram->bounds->data.F32[binNum]);
+        x->data.F64[1] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum] + histogram->bounds->data.F32[binNum + 1]);
+        x->data.F64[2] = (double)0.5 *
+                         (histogram->bounds->data.F32[binNum + 1] + histogram->bounds->data.F32[binNum + 2]);
+
+        y->data.F64[0] = cumulativeSums->data.F32[binNum - 1];
+        y->data.F64[1] = cumulativeSums->data.F32[binNum];
+        y->data.F64[2] = cumulativeSums->data.F32[binNum + 1];
+
+        if (!((y->data.F64[0] <= fitFloat) && (fitFloat <= y->data.F64[2]))) {
+            psAbort(__func__, "p_psVectorRobustStats(0): midpoint not within y-range\n");
+        }
+
+        yErr->data.F64[0] = 1.0;
+        yErr->data.F64[1] = 1.0;
+        yErr->data.F64[2] = 1.0;
+
+        myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+        return (p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], fitFloat));
+    } else {
+        return (0.5 * (histogram->bounds->data.F32[binNum + 1] + histogram->bounds->data.F32[binNum]));
+    }
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(myPoly);
+    return (0.0);
+}
+
+/******************************************************************************
+p_psVectorRobustStats(myVector, maskVector, maskVal, stats): this procedure
+calculates a variety of robust stat measures:
+    PS_STAT_ROBUST_MEAN
+    PS_STAT_ROBUST_MEDIAN
+    PS_STAT_ROBUST_MODE
+    PS_STAT_ROBUST_STDEV
+    PS_STAT_ROBUST_QUARTILE
+I have included all that computation in a single function, as opposed to
+breaking it across several functions for one primary reason:  they all
+require the same basic initial processing steps (calculate the histogram,
+etc.)  however there is no currently defined means, in the SDRS, to specify
+this computation as a separate step.  If the above robust stat measures were
+calcualted in separate functiosn, then much of the initial processing would
+be duplicated.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+*****************************************************************************/
+void p_psVectorRobustStats(const psVector* restrict myVector,
+                           const psVector* restrict maskVector, unsigned int maskVal, psStats* stats)
+{
+    psHistogram* robustHistogram = NULL;
+    psVector* robustHistogramVector = NULL;
+    float binSize = 0.0;        // Size of the histogram bins
+    int LQBinNum = -1;          // Bin num for lower quartile
+    int UQBinNum = -1;          // Bin num for upper quartile
+    int i = 0;                  // Loop index variable
+    int maxBinNum = 0;
+    float maxBinCount = 0.0;
+    float dL = 0.0;
+    int numBins = 0;
+    psStats* tmpStats = psStatsAlloc(PS_STAT_CLIPPED_STDEV | PS_STAT_CLIPPED_MEAN);
+
+    // psImage* domain;
+    // psVector* errors;
+    // psVector* data;
+    // psVector* initialGuess;
+    // psVector* theParams;
+    // float chiSq=0.0;
+    // float max = -HUGE;
+    // float max_pos;
+    float myMean = 0.0;
+    float myStdev = 0.0;
+    float countFloat = 0.0;
+    float diff = 0.0;
+    float sumSquares = 0.0;
+    float sumDiffs = 0.0;
+    psVector* x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* y = psVectorAlloc(3, PS_TYPE_F64);
+    psVector* yErr = psVectorAlloc(3, PS_TYPE_F64);
+    psPolynomial1D* myPoly = psPolynomial1DAlloc(2);
+    psVector* cumulativeRobustSumsFullRange = NULL;
+    psVector* cumulativeRobustSumsDlRange = NULL;
+    float sumRobust = 0.0;
+    float sumN50 = 0.0;
+    float sumNfit = 0.0;
+    float cumulativeMedian = 0.0;
+
+    // Compute the initial bin size of the robust histogram.  This is done
+    // by computing the clipped standard deviation of the vector, and dividing
+    // that by 10.0;
+    p_psVectorClippedStats(myVector, maskVector, maskVal, tmpStats);
+    binSize = tmpStats->clippedStdev / 10.0f;
+
+    // If stats->clippedStdev == 0.0, then all data elements have the same
+    // value.  Therefore, we can set the appropiate results and return.
+    if (fabs(binSize) <= FLT_EPSILON) {
+        if (stats->options & PS_STAT_ROBUST_MEAN) {
+            stats->robustMean = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_MEDIAN) {
+            stats->robustMedian = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_MODE) {
+            stats->robustMode = stats->clippedMean;
+        }
+        if (stats->options & PS_STAT_ROBUST_STDEV) {
+            stats->robustStdev = 0.0;
+        }
+        if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+            stats->robustUQ = stats->clippedMean;
+            stats->robustLQ = stats->clippedMean;
+        }
+        // XXX: Set these to the number of unmasked data points?
+        stats->robustNfit = 0.0;
+        stats->robustN50 = 0.0;
+        psFree(tmpStats);
+        return;
+    }
+    // Determine minimum and maximum values in the data vector.
+    if (isnan(stats->min)) {
+        p_psVectorMin(myVector, maskVector, maskVal, stats);
+    }
+    if (isnan(stats->max)) {
+        p_psVectorMax(myVector, maskVector, maskVal, stats);
+    }
+    // Create the histogram structure.  NOTE: we can not specify the bin size
+    // precisely since the argument to psHistogramAlloc() is the number of
+    // bins, not the binSize.  Also, if we get here, we know that
+    // binSize != 0.0.
+    numBins = (int)((stats->max - stats->min) / binSize);
+    robustHistogram = psHistogramAlloc(stats->min, stats->max, numBins);
+
+    // Populate the histogram array.
+    psVectorHistogram(robustHistogram, myVector, maskVector, maskVal);
+
+    // Smooth the histogram.
+    // XXX: is that the right stdev?
+    robustHistogramVector = p_psVectorsmoothHistGaussian(robustHistogram, tmpStats->clippedStdev / 4.0f);
+
+    // The following was necessary to fit a gaussian to the data, since
+    // gaussian functions produce data between 0.0 and 1.0.
+    // p_psNormalizeVector(robustHistogramVector);
+
+    /**************************************************************************
+    Determine the lower/upper quartiles.
+    **************************************************************************/
+    // We define a vector called "cumulativeRobustSums..." where the value at
+    // index position i is equal to the sum of bins 0:i.  This will be used
+    // now and later in determining the lower/upper quartiles.
+    cumulativeRobustSumsFullRange = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    cumulativeRobustSumsFullRange->data.F32[0] = robustHistogramVector->data.F32[0];
+    for (i = 1; i < robustHistogramVector->n; i++) {
+        cumulativeRobustSumsFullRange->data.F32[i] =
+            cumulativeRobustSumsFullRange->data.F32[i - 1] + robustHistogramVector->data.F32[i];
+    }
+    sumRobust = cumulativeRobustSumsFullRange->data.F32[robustHistogramVector->n - 1];
+
+    // Determine the bin number containing the lower quartile point.
+    LQBinNum = -1;
+    for (i = 0; i < cumulativeRobustSumsFullRange->n; i++) {
+        if (cumulativeRobustSumsFullRange->data.F32[i] >= (sumRobust / 4.0)) {
+            LQBinNum = i;
+            break;
+        }
+    }
+
+    // Determine the bin number containing the upper quartile point.
+    UQBinNum = -1;
+    for (i = cumulativeRobustSumsFullRange->n - 1; i >= 0; i--) {
+        if (cumulativeRobustSumsFullRange->data.F32[i] <= (3.0 * sumRobust / 4.0)) {
+            UQBinNum = i;
+            break;
+        }
+    }
+
+    if ((LQBinNum == -1) || (UQBinNum == -1)) {
+        psAbort(__func__, "Could not determine the robust lower/upper quartiles.");
+    }
+
+    /**************************************************************************
+    Determine the mode in the range LQ:UQ.
+    **************************************************************************/
+    // Determine the bin with the peak value in the range LQ to UQ.
+    maxBinNum = LQBinNum;
+    maxBinCount = robustHistogramVector->data.F32[LQBinNum];
+    sumN50 = (float)robustHistogram->nums->data.S32[LQBinNum];
+    for (i = LQBinNum + 1; i <= UQBinNum; i++) {
+        if (robustHistogramVector->data.F32[i] > maxBinCount) {
+            maxBinNum = i;
+            maxBinCount = robustHistogramVector->data.F32[i];
+        }
+        sumN50 += (float)robustHistogram->nums->data.S32[i];
+    }
+
+    // XXX: is dL defined as the value at the LQ/UQ, or the bin number?
+    dL = (UQBinNum - LQBinNum) / 4;
+
+    printf("(LQBinNum, UQBinNum, maxBinNum) is (%d, %d, %d)\n", LQBinNum, UQBinNum, maxBinNum);
+
+    /**************************************************************************
+    Determine the mean/stdev for the bins in the range mode-dL to mode+dL
+    **************************************************************************/
+    cumulativeRobustSumsDlRange = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    for (i = 0; i < robustHistogramVector->n; i++) {
+        cumulativeRobustSumsDlRange->data.F32[i] = 0.0;
+    }
+    sumNfit = 0.0;
+    cumulativeMedian = 0.0;
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            cumulativeRobustSumsDlRange->data.F32[i] =
+                cumulativeRobustSumsDlRange->data.F32[i - 1] + robustHistogramVector->data.F32[i];
+            cumulativeMedian += robustHistogramVector->data.F32[i];
+            sumNfit += (float)robustHistogram->nums->data.S32[i];
+        }
+    }
+
+    // Calculate the mean of the smoothed robust histogram in the range
+    // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
+    // that bin (this is a non-exact approximation).
+    myMean = 0.0;
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            myMean += (robustHistogramVector->data.F32[i]) * 0.5 *
+                      (robustHistogram->bounds->data.F32[i + 1] + robustHistogram->bounds->data.F32[i]);
+            countFloat += robustHistogramVector->data.F32[i];
+        }
+    }
+    myMean /= countFloat;
+
+    // Calculate the stdev of the smoothed robust histogram in the range
+    // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
+    // that bin.
+    for (i = maxBinNum - dL; i <= maxBinNum + dL; i++) {
+        if ((0 <= i) && (i < robustHistogramVector->n)) {
+            diff = (0.5 * (robustHistogram->bounds->data.F32[i + 1] +
+                           robustHistogram->bounds->data.F32[i])) - myMean;
+            sumSquares += diff * diff * robustHistogramVector->data.F32[i];
+            sumDiffs += diff * robustHistogramVector->data.F32[i];
+        }
+    }
+    myStdev = sqrt((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
+
+    /**************************************************************************
+    Set the appropriate members in the output stats struct.
+    **************************************************************************/
+    if (stats->options & PS_STAT_ROBUST_MEAN) {
+        stats->robustMean = myMean;
+    }
+
+    if (stats->options & PS_STAT_ROBUST_MODE) {
+        stats->robustMode = 0.5 *
+                            (robustHistogram->bounds->data.F32[maxBinNum] + robustHistogram->bounds->data.F32[maxBinNum + 1]);
+    }
+
+    if (stats->options & PS_STAT_ROBUST_STDEV) {
+        stats->robustStdev = myStdev;
+    }
+    // To determine the median (and later, the lower/upper quartile), we fit
+    // a quadratic to the three bins surrounding the bin containing the median.
+    // The quadratic y=f(x) with x being the midpoint of each bin, and y being
+    // the cumulative number of data points in all bins up to, and including,
+    // this bin.  We then solve the quadratic for
+
+    if (stats->options & PS_STAT_ROBUST_MEDIAN) {
+        if ((maxBinNum > 0) && (maxBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum - 1] +
+                              robustHistogram->bounds->data.F32[maxBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum] +
+                              robustHistogram->bounds->data.F32[maxBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[maxBinNum + 1] +
+                              robustHistogram->bounds->data.F32[maxBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsDlRange->data.F32[maxBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsDlRange->data.F32[maxBinNum];
+            y->data.F64[2] = cumulativeRobustSumsDlRange->data.F32[maxBinNum + 1];
+
+            // Ensure that cumulativeMedian/2 is actually within the range of the bins
+            // we are using.
+            cumulativeMedian *= 0.5;
+            if (!((y->data.F64[0] <= cumulativeMedian) && (cumulativeMedian <= y->data.F64[2]))) {
+                printf("((%f), %f, %f)\n", cumulativeMedian, y->data.F64[0], y->data.F64[2]);
+                psAbort(__func__, "p_psVectorRobustStats(1): midpoint not within y-range\n");
+            }
+            // XXX: yErr is not currently used by psVectorFitPolynomial1D().  We
+            // may have to set this meaningfully later.
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            // Determine the coefficients of the polynomial.
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            // Call p_ps1DPolyMedian(), which does a binary search on the
+            // polynomial, looking for the value x such that
+            // f(x) = cumulativeMedian.
+            stats->robustMedian = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], cumulativeMedian);
+        } else {
+            // If the mode is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustMedian = 0.5 * (robustHistogram->bounds->data.F32[maxBinNum + 1] +
+                                         robustHistogram->bounds->data.F32[maxBinNum]);
+        }
+    }
+    // The lower/upper quartile calculations are very similar to the median
+    // calculations.  We fit a quadratic to the array containing the
+    // cumulative data points in each bin, then search for x such that
+    // f(x) equals the lower/upper quartile exactly.
+    //
+    if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+        countFloat = cumulativeRobustSumsFullRange->data.F32[robustHistogramVector->n - 1];
+
+        if ((LQBinNum > 0) && (LQBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum - 1] +
+                              robustHistogram->bounds->data.F32[LQBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum] +
+                              robustHistogram->bounds->data.F32[LQBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[LQBinNum + 1] +
+                              robustHistogram->bounds->data.F32[LQBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[LQBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[LQBinNum];
+            y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[LQBinNum + 1];
+
+            if (!((y->data.F64[0] <= (countFloat / 4.0)) && ((countFloat / 4.0) <= y->data.F64[2]))) {
+                psAbort(__func__, "p_psVectorRobustStats(2): midpoint not within y-range\n");
+            }
+
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            stats->robustLQ = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], countFloat / 4.0);
+
+        } else {
+            // If the LQ is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustLQ = 0.5 * (robustHistogram->bounds->data.F32[LQBinNum + 1] +
+                                     robustHistogram->bounds->data.F32[LQBinNum]);
+        }
+
+        if ((UQBinNum > 0) && (UQBinNum < (robustHistogram->nums->n - 1))) {
+            x->data.F64[0] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum - 1] +
+                              robustHistogram->bounds->data.F32[UQBinNum]);
+            x->data.F64[1] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum] +
+                              robustHistogram->bounds->data.F32[UQBinNum + 1]);
+            x->data.F64[2] = (double)0.5 *
+                             (robustHistogram->bounds->data.F32[UQBinNum + 1] +
+                              robustHistogram->bounds->data.F32[UQBinNum + 2]);
+
+            y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[UQBinNum - 1];
+            y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[UQBinNum];
+            y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[UQBinNum + 1];
+
+            if (!((y->data.F64[0] <= (3.0 * countFloat / 4.0)) &&
+                    ((3.0 * countFloat / 4.0) <= y->data.F64[2]))) {
+                psAbort(__func__, "p_psVectorRobustStats(3): midpoint not within y-range\n");
+            }
+
+            yErr->data.F64[0] = 1.0;
+            yErr->data.F64[1] = 1.0;
+            yErr->data.F64[2] = 1.0;
+
+            myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
+            stats->robustUQ = p_ps1DPolyMedian(myPoly,
+                                               x->data.F64[0], x->data.F64[2], 3.0 * countFloat / 4.0);
+        } else {
+            // If the UQ is the first/last histogram bin, then simply use
+            // the midpoint of that bin.
+            stats->robustUQ = 0.5 * (robustHistogram->bounds->data.F32[UQBinNum + 1] +
+                                     robustHistogram->bounds->data.F32[UQBinNum]);
+        }
+    }
+    stats->robustNfit = sumNfit;
+    stats->robustN50 = sumN50;
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(tmpStats);
+    psFree(robustHistogram);
+    psFree(myPoly);
+    psFree(cumulativeRobustSumsFullRange);
+    psFree(cumulativeRobustSumsDlRange);
+}
+
+/*
+void p_ps_FitTheGaussian()
+{
+ 
+    // Fit a Gaussian to the bins in the range MODE-dL to Mode+dL
+    // NOTE: This code uses the psMinimize.c functions to perform
+    // the fit.  It doesn't quite work, 100% of the time.  For the time being
+    // I am commenting this code out, and replacing it with code which
+    // calculates the mean directly on the robustHistogram.
+ 
+    domain = psImageAlloc(1, robustHistogramVector->n, PS_TYPE_F32);
+    errors = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    data = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
+    initialGuess = psVectorAlloc(2, PS_TYPE_F32);
+ 
+    max = -HUGE;
+    max_pos = -1;
+    for (i=0;i<robustHistogramVector->n;i++) {
+        domain->data.F32[i][0] = 0.5 * (robustHistogram->bounds->data.F32[i+1] +
+                                        robustHistogram->bounds->data.F32[i]);
+        data->data.F32[i] = (float) robustHistogramVector->data.F32[i];
+        errors->data.F32[i] = 1.0;
+        //printf("DATA (%.2f, %.2f)\n", domain->data.F32[i][0], data->data.F32[i]);
+        if (data->data.F32[i] > max) {
+            max = data->data.F32[i];
+            max_pos = domain->data.F32[i][0];
+        }
+    }
+ 
+    initialGuess->data.F32[0] = max_pos;
+    initialGuess->data.F32[1] = 1.0;
+    printf("Initial (mean. stdev) is (%.3f, %.3f)\n", initialGuess->data.F32[0], initialGuess->data.F32[1]);
+ 
+    printf("Calling psMinimizeChi2()\n");
+    theParams = psMinimizeChi2(p_psGaussian,
+                               p_psGaussianDeriv,
+                               domain,
+                               data,
+                               errors,
+                               initialGuess,
+                               NULL,
+                               &chiSq);
+    printf("Called psMinimizeChi2()\n");
+    printf("p_psVectorRobustStats() is (%f, %f)\n", theParams->data.F32[0], theParams->data.F32[1]);
+}
+*/
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+static void histogramFree(psHistogram* myHist);
+
+/******************************************************************************
+    psStatsAlloc(): This routine must create a new psStats data structure.
+ *****************************************************************************/
+psStats* psStatsAlloc(psStatsOptions options)
+{
+    psStats* newStruct = NULL;
+
+    newStruct = (psStats* ) psAlloc(sizeof(psStats));
+    newStruct->sampleMean = NAN;
+    newStruct->sampleMedian = NAN;
+    newStruct->sampleStdev = NAN;
+    newStruct->sampleUQ = NAN;
+    newStruct->sampleLQ = NAN;
+    newStruct->sampleLimit = 30000;
+    newStruct->robustMean = NAN;
+    newStruct->robustMedian = NAN;
+    newStruct->robustMode = NAN;
+    newStruct->robustStdev = NAN;
+    newStruct->robustUQ = NAN;
+    newStruct->robustLQ = NAN;
+    newStruct->robustN50 = NAN;
+    newStruct->robustNfit = NAN;
+    newStruct->clippedMean = NAN;
+    newStruct->clippedStdev = NAN;
+    newStruct->clipSigma = 3.0;
+    newStruct->clipIter = 3.0;
+    newStruct->min = NAN;
+    newStruct->max = NAN;
+    newStruct->binsize = NAN;
+    newStruct->options = options;
+
+    return (newStruct);
+}
+
+/******************************************************************************
+psHistogramAlloc(lower, upper, n): allocate a uniform histogram structure
+with the specifed upper and lower limits, and the specifed number of bins.
+This routine will also set the bounds for each of the bins.
+ 
+Input:
+    lower
+    upper
+    n
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAlloc(float lower, float upper, int n)
+{
+    int i = 0;                  // Loop index variable
+    psHistogram* newHist = NULL;        // The new histogram structure
+    float binSize = 0.0;        // The histogram bin size
+
+    // NOTE: Verify that this is the correct action.
+    if (n == 0) {
+        return (NULL);
+    }
+    if (n < 0) {
+        psAbort(__func__, "psHistogramAlloc() called with bin size %d.\n", n);
+    }
+    // NOTE: Verify that this is the correct action.
+    if (lower > upper) {
+        return (NULL);
+    }
+    // Allocate memory for the new histogram structure.  If there are N
+    // bins, then there are N+1 bounds to those bins.
+    newHist = (psHistogram* ) psAlloc(sizeof(psHistogram));
+    p_psMemSetDeallocator(newHist, (psFreeFcn) histogramFree);
+    newHist->bounds = psVectorAlloc(n + 1, PS_TYPE_F32);
+    newHist->bounds->n = newHist->bounds->nalloc;
+
+    // Calculate the bounds for each bin.
+    binSize = (upper - lower) / (float)n;
+    // NOTE: Is the following necessary? It prevents the max data point
+    // from being in a non-existant bin.
+    binSize += FLT_EPSILON;
+    for (i = 0; i < n + 1; i++) {
+        newHist->bounds->data.F32[i] = lower + (binSize * (float)i);
+    }
+
+    // Allocate the bins, and initialize them to zero.
+    newHist->nums = psVectorAlloc(n, PS_TYPE_U32);
+    newHist->nums->n = newHist->nums->nalloc;
+    for (i = 0; i < newHist->nums->n; i++) {
+        newHist->nums->data.U32[i] = 0;
+    }
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = true;
+
+    return (newHist);
+}
+
+/******************************************************************************
+psHistogramAllocGenric(bounds): allocate a non-uniform histogram structure
+with the specifed bounds.
+ 
+Input:
+    bounds
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAllocGeneric(const psVector* restrict bounds)
+{
+    psHistogram* newHist = NULL;        // The new histogram structure
+    int i;                      // Loop index variable
+
+    // NOTE: Verify that this is the correct action.
+    if (bounds == NULL) {
+        // psAbort(__func__, "psHistogram requested with NULL bounds");
+        return (NULL);
+    }
+    // NOTE: Verify that this is the correct action.
+    if (bounds->n <= 1) {
+        // psAbort(__func__, "psHistogram requested with NULL bounds");
+        return (NULL);
+    }
+
+    if (bounds->type.type != PS_TYPE_F32) {
+        // psAbort(__func__, "psHistogram request a bound which is not type F32");
+        return (NULL);
+    }
+    // Allocate memory for the new histogram structure.
+    newHist = (psHistogram* ) psAlloc(sizeof(psHistogram));
+    p_psMemSetDeallocator(newHist, (psFreeFcn) histogramFree);
+    newHist->bounds = psVectorAlloc(bounds->n, PS_TYPE_F32);
+    newHist->bounds->n = newHist->bounds->nalloc;
+    for (i = 0; i < bounds->n; i++) {
+        newHist->bounds->data.F32[i] = bounds->data.F32[i];
+    }
+
+    // Allocate the bins, and initialize them to zero.  If there are N bounds,
+    // then there are N-1 bins.
+    newHist->nums = psVectorAlloc((bounds->n) - 1, PS_TYPE_U32);
+    newHist->nums->n = newHist->nums->nalloc;
+    for (i = 0; i < newHist->nums->n; i++) {
+        newHist->nums->data.U32[i] = 0;
+    }
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = false;
+
+    return (newHist);
+}
+
+static void histogramFree(psHistogram* myHist)
+{
+    psFree(myHist->bounds);
+    psFree(myHist->nums);
+}
+
+/*****************************************************************************
+psVectorHistogram(out, in, mask, maskVal): this procedure takes as input a
+preallocated and initialized histogram structure.  It fills the bins in that
+histogram structure in accordance with the input data "in" and the, possibly
+NULL, mask vector.
+ 
+Inputs:
+    out
+    in
+    mask
+    maskVal
+Returns:
+    The histogram structure "out".
+ *****************************************************************************/
+psHistogram* psVectorHistogram(psHistogram* out,
+                               const psVector* restrict in,
+                               const psVector* restrict mask, unsigned int maskVal)
+{
+    int i = 0;                  // Loop index variable
+    int j = 0;                  // Loop index variable
+    float binSize = 0.0;        // Histogram bin size
+    int binNum = 0;             // A temporary bin number
+    int numBins = 0;            // The total number of bins
+
+    // NOTE: Verify that this is the correct action.
+    if (out == NULL) {
+        return (NULL);
+    }
+    // Check the specified output histogram for type psF32
+    if (out->bounds->type.type != PS_TYPE_F32) {
+        psAbort(__func__, "Only data type PS_TYPE_F32 for the output.bounds member.");
+    }
+
+    if (out->nums->type.type != PS_TYPE_U32) {
+        psAbort(__func__, "Only data type PS_TYPE_U32 for output.nums member.");
+    }
+    // NOTE: Verify that this is the correct action.
+    if (in == NULL) {
+        return (out);
+    }
+
+    if (in->type.type != PS_TYPE_F32) {
+        psAbort(__func__, "Only data type PS_TYPE_F32 is currently supported (0x%x).", in->type.type);
+    }
+
+    if (mask != NULL) {
+        if (in->n != mask->n) {
+            psAbort(__func__, "Vector data and vector mask are of different sizes.");
+        }
+        if (mask->type.type != PS_TYPE_U8) {
+            psAbort(__func__, "Vector mask must be type PS_TYPE_U8");
+        }
+    }
+    // NOTE: determine the correct action for a variety of other cases:
+    // in vector has 0 elements, and histogram structure has zero bins.
+
+    numBins = out->nums->n;
+    for (i = 0; i < in->n; i++) {
+        // Check if this pixel is masked, and if so, skip it.
+        if ((mask == NULL) || ((mask != NULL) && (!(mask->data.U8[i] & maskVal)))) {
+            // Check if this pixel is below the minimum value, and if so
+            // count it, then skip it.
+            if (in->data.F32[i] < out->bounds->data.F32[0]) {
+                out->minNum++;
+                // Check if this pixel is above the maximum value, and if so
+                // count it, then skip it.
+            } else if (in->data.F32[i] > out->bounds->data.F32[numBins]) {
+                out->maxNum++;
+            } else {
+                // If this is a uniform histogram, determining the correct
+                // number is trivial.
+                if (out->uniform == true) {
+                    binSize = out->bounds->data.F32[1] - out->bounds->data.F32[0];
+                    binNum = (int)((in->data.F32[i] - out->bounds->data.F32[0]) / binSize);
+
+                    // NOTE: This next if-statement really shouldn't be necessary.
+                    // However, do to numerical lack of precision, we occasionally
+                    // produce a binNum outside the range of bins.
+                    if (binNum >= out->nums->n) {
+                        binNum = out->nums->n - 1;
+                    }
+
+                    (out->nums->data.S32[binNum])++;
+
+                    // If this is a non-uniform histogram, determining the correct
+                    // bin number requires a bit more work.
+                } else {
+                    // NOTE: This is slow.  Put a smarter algorithm here to
+                    // find the correct bin number (bin search, probably)
+                    for (j = 0; j < (out->bounds->n) - 1; j++) {
+                        if ((out->bounds->data.S32[j] <= in->data.F32[i]) &&
+                                (in->data.F32[i] <= out->bounds->data.S32[j + 1])) {
+                            (out->nums->data.S32[j])++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return (out);
+}
+
+/******************************************************************************
+p_psConvertToF32(myVector, maskVector, maskVal, stats): this is the cheap
+way to support a variety of vector data types: we simply convert the input
+vector to F32 at the beginning, and write all of our functions in F32.  If
+the vast majority of all vector stat operations are F32 (or any other single
+type), then this is probably the best way to go.  Otherwise, when the
+algorithms stablize, we will then macro everything and put type support in
+the various stat functions.
+ *****************************************************************************/
+psVector* p_psConvertToF32(psStats* stats, psVector* in, psVector* mask, unsigned int maskVal)
+{
+    int i = 0;
+    psVector* tmp = NULL;
+
+    if (in->type.type == PS_TYPE_S32) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.S32[i];
+        }
+    } else if (in->type.type == PS_TYPE_U32) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.U32[i];
+        }
+    } else if (in->type.type == PS_TYPE_F64) {
+        tmp = psVectorAlloc(in->n, PS_TYPE_F32);
+        for (i = 0; i < in->n; i++) {
+            tmp->data.F32[i] = (float)in->data.F64[i];
+        }
+    } else if (in->type.type == PS_TYPE_F32) {
+        // do nothing
+    } else {
+        psAbort(__func__, "unsupported vector type 0x%x\n", in->type.type);
+    }
+    return (tmp);
+}
+
+/******************************************************************************
+psVectorStats(myVector, maskVector, maskVal, stats): this is the public API
+function which calls the above private stats functions based on what bits
+were set in stats->options.
+ 
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    The stats structure.
+ 
+NOTE: The current strategy is to implement everything assuming that all
+input data is of type PS_TYPE_F32.  Once the basic code is in place, we will
+macro-ize everything and add PS_TYPE_U16 and PS_TYPE_F64.
+ *****************************************************************************/
+psStats* psVectorStats(psStats* stats, psVector* in, psVector* mask, unsigned int maskVal)
+{
+    psVector* inF32;
+    int mustFreeTmp = 1;
+
+    // NOTE: Verify that this is the correct action.
+    if (in == NULL) {
+        return (stats);
+    }
+    if (stats == NULL) {
+        return (NULL);
+    }
+
+    inF32 = p_psConvertToF32(stats, in, mask, maskVal);
+    if (inF32 == NULL) {
+        inF32 = in;
+        mustFreeTmp = 0;
+    }
+    // XXX: Should we abort if (stats->min == stats->max)?
+    if ((stats->options & PS_STAT_USE_RANGE) && (stats->min >= stats->max)) {
+        psAbort(__func__, "psVectorStats() called with range: %f to %f\n", stats->min, stats->max);
+    }
+    // PS_CHECK_VECTOR_TYPE(in, PS_TYPE_F32);
+    if (mask != NULL) {
+        PS_CHECK_NULL_VECTOR(mask);
+        PS_CHECK_EMPTY_VECTOR(mask);
+        PS_CHECK_VECTOR_SIZE_EQUAL(mask, in);
+        PS_CHECK_VECTOR_TYPE(mask, PS_TYPE_U8);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_MEAN) {
+        p_psVectorSampleMean(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_MEDIAN) {
+        p_psVectorSampleMedian(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    // NOTE: The Stdev calculation requires the mean.  Should we assume the
+    // mean has already been calculated? Or should we always calculate it?
+    if (stats->options & PS_STAT_SAMPLE_STDEV) {
+        p_psVectorSampleMean(in, mask, maskVal, stats);
+        p_psVectorSampleStdev(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_QUARTILE) {
+        p_psVectorSampleQuartiles(in, mask, maskVal, stats);
+    }
+    // Since the various robust stats quantities share much computation, they
+    // are grouped together in a single private function:
+    // p_psVectorRobustStats()
+    if ((stats->options & PS_STAT_ROBUST_MEAN) ||
+            (stats->options & PS_STAT_ROBUST_MEDIAN) ||
+            (stats->options & PS_STAT_ROBUST_MODE) ||
+            (stats->options & PS_STAT_ROBUST_STDEV) || (stats->options & PS_STAT_ROBUST_QUARTILE)) {
+        p_psVectorRobustStats(in, mask, maskVal, stats);
+    }
+
+    if ((stats->options & PS_STAT_CLIPPED_MEAN) || (stats->options & PS_STAT_CLIPPED_STDEV)) {
+        p_psVectorClippedStats(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_MAX) {
+        p_psVectorMax(in, mask, maskVal, stats);
+    }
+    // ************************************************************************
+    if (stats->options & PS_STAT_MIN) {
+        p_psVectorMin(in, mask, maskVal, stats);
+    }
+
+    if (mustFreeTmp == 1) {
+        psFree(inF32);
+    }
+    return (stats);
+}
Index: /tags/rel2_1/psLib/src/math/psStats.h
===================================================================
--- /tags/rel2_1/psLib/src/math/psStats.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/math/psStats.h	(revision 1553)
@@ -0,0 +1,185 @@
+
+/** @file  psStats.h
+ *  \brief basic statistical operations
+ *  @ingroup Stats
+ *
+ *  This file will hold the definition of the histogram and stats data
+ *  structures.  It also contains prototypes for procedures which operate
+ *  on those data structures.
+ *
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:16:04 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_STATS_H)
+#define PS_STATS_H
+
+#include "psVector.h"
+
+/// @addtogroup Stats
+/// @{
+
+/******************************************************************************
+    Statistical functions and data structures.
+ *****************************************************************************/
+
+/** enumeration of statistical calculation options
+ *
+ *  @see psStats, psVectorStats, psImageStats
+ */
+typedef enum {
+    PS_STAT_SAMPLE_MEAN = 0x000001,
+    PS_STAT_SAMPLE_MEDIAN = 0x000002,
+    PS_STAT_SAMPLE_STDEV = 0x000004,
+    PS_STAT_SAMPLE_QUARTILE = 0x000008,
+    PS_STAT_ROBUST_MEAN = 0x000010,
+    PS_STAT_ROBUST_MEDIAN = 0x000020,
+    PS_STAT_ROBUST_MODE = 0x000040,
+    PS_STAT_ROBUST_STDEV = 0x000080,
+    PS_STAT_ROBUST_QUARTILE = 0x000100,
+    PS_STAT_CLIPPED_MEAN = 0x000200,
+    PS_STAT_CLIPPED_STDEV = 0x000400,
+    PS_STAT_MAX = 0x000800,
+    PS_STAT_MIN = 0x001000,
+    PS_STAT_USE_RANGE = 0x002000,
+    PS_STAT_USE_BINSIZE = 0x004000,
+    PS_STAT_ROBUST_FOR_SAMPLE = 0x008000
+} psStatsOptions;
+
+/** This is the generic statistics structure.  It contails the data members
+    for the various statistic values.  It also contains the options member to
+    specifiy which statistics should be calculated. */
+typedef struct
+{
+    double sampleMean;          ///< formal mean of sample
+    double sampleMedian;        ///< formal median of sample
+    double sampleStdev;         ///< standard deviation of sample
+    double sampleUQ;            ///< upper quartile of sample
+    double sampleLQ;            ///< lower quartile of sample
+    double sampleLimit;         ///<
+    double robustMean;          ///< robust mean of array
+    double robustMedian;        ///< robust median of array
+    double robustMode;          ///< Robust mode of array
+    double robustStdev;         ///< robust standard deviation of array
+    double robustUQ;            ///< robust upper quartile
+    double robustLQ;            ///< robust lower quartile
+    double XXX;
+    double robustN50;           ///<
+    double robustNfit;          ///<
+    double clippedMean;         ///< Nsigma clipped mean
+    double clippedStdev;        ///< standard deviation after clipping
+    double clipSigma;           ///< Nsigma used for clipping; user input
+    int clipIter;               ///< Number of clipping iterations; user input
+    double min;                 ///< minimum data value in array
+    double max;                 ///< maximum data value in array
+    double binsize;             ///<
+    psStatsOptions options;     ///< bitmask of calculated values
+}
+psStats;
+
+/** Performs statistical calculations on a vector.
+ *
+ *  @return psStats*    the statistical results as specified by stats->options
+ */
+psStats* psVectorStats(
+    psStats* stats,
+    ///< stats structure defines stats to be calculated and how
+
+    psVector* in,
+    ///< Vector to be analysed: must be F32
+
+    psVector* mask,
+    ///< Ignore elements where (maskVector & maskVal) != 0: must be INT or NULL
+
+    unsigned int maskVal
+    ///< Only mask elements with one of these bits set in maskVector
+);
+
+/** Allocator of the psStats structure.
+ *
+ *  @return psStats*    A new psStats struct with the options member set to the
+ *                      value given.
+ */
+psStats* psStatsAlloc(
+    psStatsOptions options             ///< Statistics to calculate
+);
+
+/******************************************************************************
+    Histogram functions and data structures.
+ *****************************************************************************/
+
+/** The basic histogram structure which contains bounds and bins.
+ *
+ *  In this structure, the vector bounds specifies the boundaries of the 
+ *  histogram bins, and must of type psF32, while nums specifies the number 
+ *  of entries in the bin, and must of type psU32. The value of bounds.n must 
+ *  therefore be 1 greater than than nums.n. The two values minNum and maxNum 
+ *  are the number of data values which fell below the lower limit bound or 
+ *  above the upper limit bound, respectively.
+ */
+typedef struct
+{
+    psVector* bounds;                  ///< Bounds for the bins (type F32)
+    psVector* nums;                    ///< Number in each of the bins (INT)
+    int minNum;                        ///< Number below the minimum
+    int maxNum;                        ///< Number above the maximum
+    bool uniform;                      ///< Is it a uniform distribution?
+}
+psHistogram;
+
+/** Allocator for psHistogram where the bounds of the bins are implicitly
+ *  specified through simply specifying an upper and lower limit along with 
+ *  the size of the bins. 
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAlloc(
+    float lower,                       ///< Lower limit for the bins
+    float upper,                       ///< Upper limit for the bins
+    int n                              ///< Number of bins
+);
+
+/** Allocator for psHistogram where the bounds of the bins are explicitly
+ *  specified. 
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAllocGeneric(
+    const psVector* restrict bounds    ///< Bounds for the bins
+);
+
+/** Calculate a histogram
+ *
+ *  The following function populates the histogram bins from the specified 
+ *  vector (in). It alters and returns the histogram out structure. The input
+ *  vector may be of types psU8, psU16, psF32, psF64.
+ *
+ *  @return psHistogram*   histogram result
+ */
+psHistogram* psVectorHistogram(
+    psHistogram* out,                  ///< Histogram data
+    const psVector* restrict in,       ///< Vector to analyse
+    const psVector* restrict mask,     ///< Mask dat for input vector
+    unsigned int maskVal               ///< Mask value
+);
+
+/** Extracts the statistic value specified by stats->options.
+ *
+ *  @return bool    If more than one statistic result is set in stats->options,
+ *                  false is returned and the value parameter is not set, 
+ *                  otherwise true is returned.
+ */
+bool p_psGetStatValue(
+    const psStats* stats,
+    ///< the statistic struct to operate on
+
+    double *value
+    ///< if return is true, this is set to the specified statistic value by stats->options
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/mathtypes/psImage.c
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psImage.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psImage.c	(revision 1553)
@@ -0,0 +1,436 @@
+
+/** @file  psImage.c
+ *
+ *  @brief Contains basic image definitions and operations.
+ *
+ *  This file defines the basic type for an image struct and functions useful
+ *  in manupulating images.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ *  That is the routine used to generate matrices.
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+
+#include <string.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psAbort.h"
+#include "psError.h"
+#include "psImage.h"
+
+static void imageFree(psImage* image);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+psImage* psImageAlloc(unsigned int numCols, unsigned int numRows, const psElemType type)
+{
+    int area = 0;
+    int elementSize = PSELEMTYPE_SIZEOF(type);  // element
+
+    // size in
+    // bytes
+    int rowSize = numCols * elementSize;        // row
+
+    // size
+
+    // in bytes.
+
+    area = numCols * numRows;
+
+    if (area < 1) {
+        psError(__func__,
+                "Invalid value for number of rows or columns " "(numRows=%d, numCols=%d).", numRows, numCols);
+        return NULL;
+    }
+
+    psImage* image = (psImage* ) psAlloc(sizeof(psImage));
+
+    if (image == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    p_psMemSetDeallocator(image, (psFreeFcn) imageFree);
+
+    image->data.V = psAlloc(sizeof(void *) * numRows);
+    if (image->data.V == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    image->data.V[0] = psAlloc(area * elementSize);
+    if (image->data.V[0] == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    for (int i = 1; i < numRows; i++) {
+        image->data.V[i] = (void *)((int8_t *) image->data.V[i - 1] + rowSize);
+    }
+
+    *(int *)&image->col0 = 0;
+    *(int *)&image->row0 = 0;
+    *(unsigned int *)&image->numCols = numCols;
+    *(unsigned int *)&image->numRows = numRows;
+    *(psDimen* ) & image->type.dimen = PS_DIMEN_IMAGE;
+    *(psElemType* ) & image->type.type = type;
+    image->parent = NULL;
+    image->nChildren = 0;
+    image->children = NULL;
+
+    return image;
+}
+
+static void imageFree(psImage* image)
+{
+    if (image == NULL) {
+        return;
+    }
+
+    if (image->type.type == PS_TYPE_PTR) {
+        // 2-D array of pointers -- must
+        // dereference
+        unsigned int oldNumRows = image->numRows;
+        unsigned int oldNumCols = image->numCols;
+        psPTR* rowPtr;
+
+        for (unsigned int row = 0; row < oldNumRows; row++) {
+            rowPtr = image->data.PTR[row];
+            for (unsigned int col = 0; col < oldNumCols; col++) {
+                psMemDecrRefCounter(rowPtr[col]);
+            }
+        }
+    }
+
+    psImageFreeChildren(image);
+
+    psFree(image->data.V[0]);
+    psFree(image->data.V);
+    image->data.V = NULL;
+}
+
+psImage* psImageRecycle(psImage* old, unsigned int numCols, unsigned int numRows, const psElemType type)
+{
+    int elementSize = PSELEMTYPE_SIZEOF(type);  // element
+
+    // size in
+    // bytes
+    int rowSize = numCols * elementSize;        // row
+
+    // size
+
+    // in bytes.
+
+    if (old == NULL) {
+        old = psImageAlloc(numCols, numRows, type);
+        return old;
+    }
+
+    if (old->type.dimen != PS_DIMEN_IMAGE) {
+        psError(__func__, "Can not realloc image because input is not an image.");
+        return NULL;
+    }
+
+    if (old->type.type == PS_TYPE_PTR) {
+        // 2-D array of pointers -- must
+        // dereference
+        unsigned int oldNumRows = old->numRows;
+        unsigned int oldNumCols = old->numCols;
+        psPTR* rowPtr;
+
+        for (unsigned int row = 0; row < oldNumRows; row++) {
+            rowPtr = old->data.PTR[row];
+            for (unsigned int col = 0; col < oldNumCols; col++) {
+                psMemDecrRefCounter(rowPtr[col]);
+                rowPtr[col] = NULL;
+            }
+        }
+    }
+
+    /* image already the right size/type? */
+    if (numCols == old->numCols && numRows == old->numRows && type == old->type.type) {
+        return old;
+    }
+    // Resize the image buffer
+    old->data.V[0] = psRealloc(old->data.V[0], numCols * numRows * elementSize);
+    old->data.V = (void **)psRealloc(old->data.V, numRows * sizeof(void *));
+
+    // recreate the row pointers
+    for (int i = 1; i < numRows; i++) {
+        old->data.V[i] = (void *)((int8_t *) old->data.V[i - 1] + rowSize);
+    }
+
+    *(unsigned int *)&old->numCols = numCols;
+    *(unsigned int *)&old->numRows = numRows;
+    *(psElemType* ) & old->type.type = type;
+
+    return old;
+}
+
+int psImageFreeChildren(psImage* image)
+{
+    int i = 0;
+    int nChildren = 0;
+    psImage* *children = NULL;
+    int numFreed = 0;
+
+    if (image == NULL) {
+        return numFreed;
+    }
+
+    nChildren = image->nChildren;
+    children = image->children;
+
+    for (i = 0; i < nChildren; i++) {
+        if (children[i] != NULL) {
+            numFreed++;
+            psFree(children[i]);
+        }
+    }
+    psFree(children);
+
+    image->nChildren = 0;
+    image->children = NULL;
+
+    return numFreed;
+}
+
+/*****************************************************************************
+p_psImagePixelInterpolation(image, x, y): this routine takes as input an
+image and coordinates (x, y) and produces as output the corresponding pixel
+value at the those coordinates.  For fractional corrdinates (x, y), 2-D
+linear interpolation is performed on the image.
+ *****************************************************************************/
+psF32 psImagePixelInterpolate(const psImage* input,
+                              float x, float y, psF32 unexposedValue, psImageInterpolateMode mode)
+{
+
+    if (input == NULL) {
+        psError(__func__, "Image can not be NULL.");
+        return unexposedValue;
+    }
+    #define PSIMAGE_PIXEL_INTERPOLATE_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    switch (mode) { \
+    case PS_INTERPOLATE_FLAT: \
+        return p_psImagePixelInterpolateFLAT_##TYPE(input,x,y,unexposedValue); \
+        break; \
+    case PS_INTERPOLATE_BILINEAR: \
+        return p_psImagePixelInterpolateBILINEAR_##TYPE(input,x,y,unexposedValue); \
+        break; \
+    default: \
+        psError(__func__,"Unsupported interpolation mode (#%d)",mode); \
+    } \
+    break
+
+    switch (input->type.type) {
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U8);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U16);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(U64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S8);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S16);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(S64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(F32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(F64);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(C32);
+        PSIMAGE_PIXEL_INTERPOLATE_CASE(C64);
+    default:
+        psError(__func__, "Unsupported image datatype (%d)", input->type.type);
+    }
+
+    return unexposedValue;
+}
+
+#define PSIMAGE_PIXEL_INTERPOLATE_FLAT(TYPE) \
+inline psF64 p_psImagePixelInterpolateFLAT_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue) \
+{ \
+    int intX = (int) round((psF64)(x) - 0.5); \
+    int intY = (int) round((psF64)(y) - 0.5); \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    \
+    if ((intX < 0) || \
+            (intX > lastX) || \
+            (intY < 0) || \
+            (intY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    return input->data.TYPE[intY][intX]; \
+}
+
+#define PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(TYPE) \
+inline psC64 p_psImagePixelInterpolateFLAT_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue) \
+{ \
+    int intX = (int) round((psF64)(x) - 0.5); \
+    int intY = (int) round((psF64)(y) - 0.5); \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    \
+    if ((intX < 0) || \
+            (intX > lastX) || \
+            (intY < 0) || \
+            (intY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    return input->data.TYPE[intY][intX]; \
+}
+
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U8)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U16)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(U64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S8)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S16)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(S64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(F32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT(F64)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(C32)
+PSIMAGE_PIXEL_INTERPOLATE_FLAT_COMPLEX(C64)
+#define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(TYPE) \
+inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue) \
+{ \
+    double floorX = floor((psF64)(x) - 0.5); \
+    double floorY = floor((psF64)(y) - 0.5); \
+    double fracX = x - 0.5 - floorX; \
+    double fracY = y - 0.5 - floorY; \
+    int intFloorX = (int) floorX; \
+    int intFloorY = (int) floorY; \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    double rx = 0.0; \
+    psF64 pixel = 0.0; \
+    ps##TYPE* currentRow; \
+    ps##TYPE* nextRow; \
+    \
+    if ((intFloorX < 0) || \
+            (intFloorX > lastX) || \
+            (intFloorY < 0) || \
+            (intFloorY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    currentRow = input->data.TYPE[intFloorY]; \
+    if (intFloorY == lastY) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorX < lastX) { \
+            pixel+= fracY * ((psF64)currentRow[intFloorX+1] - \
+                             (psF64)currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    nextRow = input->data.TYPE[intFloorY+1]; \
+    if (intFloorX == lastX) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorY < lastY) { \
+            pixel+= fracX * ((psF64)nextRow[intFloorX] - \
+                             (psF64)currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    \
+    rx = currentRow[intFloorX] + \
+         fracX * ((psF64)currentRow[intFloorX+1] - \
+                  (psF64)currentRow[intFloorX]); \
+    \
+    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
+                          fracX * ((psF64)nextRow[intFloorX+1] - \
+                                   (psF64)nextRow[intFloorX]) - rx); \
+    \
+    return(pixel); \
+}
+#define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(TYPE) \
+inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue) \
+{ \
+    double floorX = floor((psF64)(x) - 0.5); \
+    double floorY = floor((psF64)(y) - 0.5); \
+    double fracX = x - 0.5 - floorX; \
+    double fracY = y - 0.5 - floorY; \
+    int intFloorX = (int) floorX; \
+    int intFloorY = (int) floorY; \
+    int lastX = input->numCols - 1; \
+    int lastY = input->numRows - 1; \
+    double rx = 0.0; \
+    psC64 pixel = 0.0; \
+    ps##TYPE* currentRow; \
+    ps##TYPE* nextRow; \
+    \
+    if ((intFloorX < 0) || \
+            (intFloorX > lastX) || \
+            (intFloorY < 0) || \
+            (intFloorY > lastY)) { \
+        return unexposedValue; \
+    } \
+    \
+    currentRow = input->data.TYPE[intFloorY]; \
+    if (intFloorY == lastY) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorX < lastX) { \
+            pixel+= fracY * (currentRow[intFloorX+1] - \
+                             currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    nextRow = input->data.TYPE[intFloorY+1]; \
+    if (intFloorX == lastX) { \
+        pixel = currentRow[intFloorX]; \
+        if (intFloorY < lastY) { \
+            pixel+= fracX * (nextRow[intFloorX] - \
+                             currentRow[intFloorX]); \
+        } \
+        return(pixel); \
+    } \
+    \
+    rx = currentRow[intFloorX] + \
+         fracX * (currentRow[intFloorX+1] - \
+                  currentRow[intFloorX]); \
+    \
+    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
+                          fracX * (nextRow[intFloorX+1] - \
+                                   nextRow[intFloorX]) - rx); \
+    \
+    return(pixel); \
+}
+
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U8)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U16)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(U64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S8)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S16)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(S64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(F32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR(F64)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(C32)
+PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(C64)
Index: /tags/rel2_1/psLib/src/mathtypes/psImage.h
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psImage.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psImage.h	(revision 1553)
@@ -0,0 +1,162 @@
+
+/** @file  psImage.h
+ *
+ *  @brief Contains basic image definitions and operations
+ *
+ *  This file defines the basic type for an image struct and functions useful
+ *  in manupulating images.
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:05:53 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGE_H
+#define PS_IMAGE_H
+
+#include <complex.h>
+
+#include "psType.h"
+
+/// @addtogroup Image
+/// @{
+
+/** enumeration of options in interpolation
+ *
+ */
+typedef enum {
+    PS_INTERPOLATE_FLAT,               ///< 'flat' interpolation (nearest pixel)
+    PS_INTERPOLATE_BILINEAR            ///< bi-linear interpolation
+} psImageInterpolateMode;
+
+/** Basic image data structure.
+ *
+ * Struct for maintaining image data of varying types. It also contains
+ * information about image size, parent images and children images.
+ *
+ */
+typedef struct psImage
+{
+    const psType type;                 ///< Image data type and dimension.
+    const unsigned int numCols;        ///< Number of columns in image
+    const unsigned int numRows;        ///< Number of rows in image.
+    const int col0;                    ///< Column position relative to parent.
+    const int row0;                    ///< Row position relative to parent.
+
+    union {
+        psU8* *U8;                     ///< Unsigned 8-bit integer data.
+        psU16* *U16;                   ///< Unsigned 16-bit integer data.
+        psU32* *U32;                   ///< Unsigned 32-bit integer data.
+        psU64* *U64;                   ///< Unsigned 64-bit integer data.
+        psS8* *S8;                     ///< Signed 8-bit integer data.
+        psS16* *S16;                   ///< Signed 16-bit integer data.
+        psS32* *S32;                   ///< Signed 32-bit integer data.
+        psS64* *S64;                   ///< Signed 64-bit integer data.
+        psF32* *F32;                   ///< Single-precision float data.
+        psF64* *F64;                   ///< Double-precision float data.
+        psC32* *C32;                   ///< Single-precision complex data.
+        psC64* *C64;                   ///< Double-precision complex data.
+        psPTR* *PTR;                   ///< Void pointers.
+        psPTR* V;                      ///< Pointer to data.
+    } data;                            ///< Union for data types.
+    const struct psImage* parent;      ///< Parent, if a subimage.
+    int nChildren;                     ///< Number of subimages.
+    struct psImage* *children;         ///< Children of this region.
+}
+psImage;
+
+/** Create an image of the specified size and type.
+ *
+ * Uses psLib memory allocation functions to create an image struct of the
+ * specified size and type.
+ *
+ * @return psImage* : Pointer to psImage.
+ *
+ */
+psImage* psImageAlloc(
+    unsigned int numCols,              ///< Number of rows in image.
+    unsigned int numRows,              ///< Number of columns in image.
+    const psElemType type              ///< Type of data for image.
+);
+
+/** Resize a given image to the given size/type.
+ *
+ *  @return psImage* Resized psImage.
+ *
+ */
+psImage* psImageRecycle(
+    psImage* old,                      ///< the psImage to recycle by resizing image buffer
+    unsigned int numCols,              ///< the desired number of columns in image
+    unsigned int numRows,              ///< the desired number of rows in image
+    const psElemType type              ///< the desired datatype of the image
+);
+
+/** Frees all children of a psImage.
+ *
+ *  @return int      Number of children freed.
+ *
+ */
+int psImageFreeChildren(
+    psImage* image                     ///< psImage in which all children shall be deallocated
+);
+
+/** Interpolate image pixel value given floating point coordinates.
+ *
+ *  @return psF32    Pixel value interpolated from image or unexposedValue if
+ *                   given x,y doesn't coorespond to a valid image location
+ */
+psF32 psImagePixelInterpolate(
+    const psImage* input,              ///< input image for interpolation
+    float x,                           ///< column location to derive value of
+    float y,                           ///< row location ot derive value of
+    psF32 unexposedValue,              ///< return value if x,y location is not in image.
+    psImageInterpolateMode mode        ///< interpolation mode
+);
+
+#define p_psImagePixelInterpolateFcns(TYPE) \
+inline psF64 p_psImagePixelInterpolateFLAT_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue \
+                                                 ); \
+inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psF64 unexposedValue \
+                                                     );
+
+#define p_psImagePixelInterpolateComplexFcns(TYPE) \
+inline psC64 p_psImagePixelInterpolateFLAT_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue \
+                                                 ); \
+inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
+        const psImage* input, \
+        float x, \
+        float y, \
+        psC64 unexposedValue \
+                                                     );
+
+p_psImagePixelInterpolateFcns(U8)
+p_psImagePixelInterpolateFcns(U16)
+p_psImagePixelInterpolateFcns(U32)
+p_psImagePixelInterpolateFcns(U64)
+p_psImagePixelInterpolateFcns(S8)
+p_psImagePixelInterpolateFcns(S16)
+p_psImagePixelInterpolateFcns(S32)
+p_psImagePixelInterpolateFcns(S64)
+p_psImagePixelInterpolateFcns(F32)
+p_psImagePixelInterpolateFcns(F64)
+p_psImagePixelInterpolateComplexFcns(C32)
+p_psImagePixelInterpolateComplexFcns(C64)
+/// @}
+#endif
Index: /tags/rel2_1/psLib/src/mathtypes/psScalar.c
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psScalar.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psScalar.c	(revision 1553)
@@ -0,0 +1,153 @@
+
+/** @file  psScalar.c
+ *
+ *  @brief Contains basic scalar definitions and operations
+ *
+ *  This file defines the basic type for a scalar struct and functions useful
+ *  in manupulating scalars.
+ * *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 19:27:47 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include "psMemory.h"
+#include "psError.h"
+#include "psScalar.h"
+#include "psLogMsg.h"
+#include "psAbort.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psScalar* psScalarAlloc(psC64 value, psElemType dataType)
+{
+    psScalar* scalar = NULL;
+
+    // Create scalar
+    scalar = (psScalar* ) psAlloc(sizeof(psScalar));
+    if (scalar == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    scalar->type.dimen = PS_DIMEN_SCALAR;
+    scalar->type.type = dataType;
+
+    switch (dataType) {
+    case PS_TYPE_S8:
+        scalar->data.S8 = (psS8) value;
+        break;
+    case PS_TYPE_U8:
+        scalar->data.U8 = (psU8) value;
+        break;
+    case PS_TYPE_S16:
+        scalar->data.S16 = (psS16) value;
+        break;
+    case PS_TYPE_U16:
+        scalar->data.U16 = (psU16) value;
+        break;
+    case PS_TYPE_S32:
+        scalar->data.S32 = (psS32) value;
+        break;
+    case PS_TYPE_U32:
+        scalar->data.U32 = (psU32) value;
+        break;
+    case PS_TYPE_S64:
+        scalar->data.S64 = (psS64) value;
+        break;
+    case PS_TYPE_U64:
+        scalar->data.U64 = (psU64) value;
+        break;
+    case PS_TYPE_F32:
+        scalar->data.F32 = (psF32) value;
+        break;
+    case PS_TYPE_F64:
+        scalar->data.F64 = (psF64) value;
+        break;
+    case PS_TYPE_C32:
+        scalar->data.C32 = (psC32) value;
+        break;
+    case PS_TYPE_C64:
+        scalar->data.C64 = (psC64) value;
+        break;
+    default:
+        psError(__func__, ": Line %d - Invalid PS_TYPE: %d", __LINE__, dataType);
+    }
+
+    return scalar;
+}
+
+psScalar* psScalarCopy(psScalar *scalar)
+{
+    psScalar *newScalar = NULL;
+
+    if (scalar == NULL) {
+        psError(__func__, "Null scalar not allowed");
+    }
+
+    newScalar =  psScalarAlloc(scalar->data.C64, scalar->type.type);
+    if (newScalar == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    return newScalar;
+}
+
+void psScalarFree(psScalar* restrict scalar)
+{
+    if (scalar == NULL) {
+        return;
+    }
+
+    psFree(scalar);
+}
Index: /tags/rel2_1/psLib/src/mathtypes/psScalar.h
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psScalar.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psScalar.h	(revision 1553)
@@ -0,0 +1,93 @@
+
+/** @file  psScalar.h
+ *
+ *  @brief Contains basic scalar definitions and operations
+ *
+ *  This file defines the basic type for a scalar struct and functions useful
+ *  in manupulating scalars.
+ *
+ *  @ingroup Scalar
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:08:08 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_SCALAR_H
+#define PS_SCALAR_H
+
+#include "psType.h"
+
+/// @addtogroup Scalar
+/// @{
+
+/** Basic scalar data structure.
+ *
+ * Struct for maintaining a scalar of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psType type;                ///< Type of data.
+
+    union {
+        psU8 U8;                ///< Unsigned 8-bit integer data.
+        psU16 U16;              ///< Unsigned 16-bit integer data.
+        psU32 U32;              ///< Unsigned 32-bit integer data.
+        psU64 U64;              ///< Unsigned 64-bit integer data.
+        psS8 S8;                ///< Signed 8-bit integer data.
+        psS16 S16;              ///< Signed 16-bit integer data.
+        psS32 S32;              ///< Signed 32-bit integer data.
+        psS64 S64;              ///< Signed 64-bit integer data.
+        psF32 F32;              ///< Single-precision float data.
+        psF64 F64;              ///< Double-precision float data.
+        psC32 C32;              ///< Single-precision complex data.
+        psC64 C64;              ///< Double-precision complex data.
+    } data;                     ///< Union for data types.
+}
+psScalar;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a scalar.
+ *
+ * Uses psLib memory allocation functions to create scalar data as defined by the psType type.
+ * Accepts a complex 64 bit float for input value, as max size, but resizes according to
+ * correct type.
+ *
+ * @return psScalar*   Pointer to a new psScalar.
+ */
+psScalar* psScalarAlloc(
+    psC64 value,                       ///< Data to be put into psScalar.
+    psElemType dataType                ///< Type of data to be held by psScalar.
+);
+
+/** Deallocate a scalar.
+ *
+ * Uses psLib memory allocation functions to deallocate a scalar.
+ *
+ */
+void psScalarFree(
+    psScalar* restrict scalar          ///< Scalar to free.
+);
+
+/** Copy a scalar.
+ *
+ * Uses psLib memory allocation functions to copy a scalar.
+ *
+ * @return psScalar*    A copy of the input scalar
+ */
+psScalar* psScalarCopy(
+    psScalar *scalar                   ///< Scalar to copy.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/mathtypes/psVector.c
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psVector.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psVector.c	(revision 1553)
@@ -0,0 +1,357 @@
+
+/** @file  psVector.c
+*
+*  @brief Contains support for basic vector types
+*
+*  This file defines the basic type for a vector struct and functions useful
+*  in manupulating vectors.
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>                        // for memcpy
+#include <stdlib.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psVector.h"
+#include "psLogMsg.h"
+#include "psCompare.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void vectorFree(psVector* restrict psVec);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psVector* psVectorAlloc(unsigned int nalloc, psElemType elemType)
+{
+    psVector* psVec = NULL;
+    int elementSize = 0;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);
+        return NULL;
+    }
+
+    elementSize = PSELEMTYPE_SIZEOF(elemType);
+
+    // Create vector struct
+    psVec = (psVector* ) psAlloc(sizeof(psVector));
+    p_psMemSetDeallocator(psVec, (psFreeFcn) vectorFree);
+
+    psVec->type.dimen = PS_DIMEN_VECTOR;
+    psVec->type.type = elemType;
+    psVec->nalloc = nalloc;
+    psVec->n = nalloc;
+
+    // Create vector data array
+    psVec->data.V = psAlloc(nalloc * elementSize);
+
+    return psVec;
+}
+
+psVector* psVectorRealloc(unsigned int nalloc, psVector* restrict in)
+{
+    int elementSize = 0;
+    psElemType elemType;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for realloc (%d)\n", nalloc);
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "Null input vector\n");
+        return NULL;
+    } else if (in->nalloc != nalloc) {     // No need to realloc to same size
+        elemType = in->type.type;
+        elementSize = PSELEMTYPE_SIZEOF(elemType);
+        if (nalloc < in->n) {
+            in->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        in->data.V = psRealloc(in->data.V, nalloc * elementSize);
+        in->nalloc = nalloc;
+    }
+
+    return in;
+}
+
+psVector* psVectorRecycle(psVector* restrict in, unsigned int nalloc, psElemType type)
+{
+    psElemType elemType;
+
+    if (in == NULL) {
+        return psVectorAlloc(nalloc, type);
+    }
+
+    elemType = in->type.type;
+
+    if (in->nalloc == nalloc && elemType == type) {
+        // it is proper size/type already
+        return in;
+    }
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc (%d)\n", nalloc);
+        psFree(in);
+        return NULL;
+    }
+
+    in->data.V = psRealloc(in->data.V, nalloc * PSELEMTYPE_SIZEOF(type));
+
+    in->type.type = type;
+    in->nalloc = nalloc;
+    in->n = nalloc;
+
+    return in;
+}
+
+psVector* psVectorSort(psVector* restrict outVector, const psVector* restrict inVector)
+{
+    int inN = 0;
+    int outN = 0;
+    int elSize = 0;
+    void *inVec = NULL;
+    void *outVec = NULL;
+    psElemType inType = 0;
+
+    if (inVector == NULL) {
+        psError(__func__, " : Line %d - Null input vector\n", __LINE__);
+        return outVector;
+    }
+
+    inType = inVector->type.type;
+    inN = inVector->n;
+    inVec = inVector->data.V;
+    elSize = PSELEMTYPE_SIZEOF(inType);
+
+    if (outVector == NULL) {
+        outVector = psVectorAlloc(inN, inType);
+        outVector->n = inVector->n;
+    }
+
+    outN = outVector->n;
+    outVec = outVector->data.V;
+
+    if (inN != outN) {
+        psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",
+                __LINE__, inN, outN);
+        return outVector;
+    }
+
+    if (inType != outVector->type.type) {
+        psError(__func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__,
+                inType, outVector->type.type);
+        return outVector;
+    }
+
+    if (inN == 0) {
+        psError(__func__, " : Line %d - No elements in use for input vector\n", __LINE__);
+        return outVector;
+    }
+
+    if (outN == 0) {
+        psError(__func__, " : Line %d - No elements in use for output vector\n", __LINE__);
+        return outVector;
+    }
+    // Copy input vector values into output vector
+    memcpy(outVec, inVec, elSize * outN);
+
+    // Sort output vector
+    switch (inType) {
+    case PS_TYPE_U8:
+        qsort(outVec, inN, elSize, psCompareU8);
+        break;
+    case PS_TYPE_U16:
+        qsort(outVec, inN, elSize, psCompareU16);
+        break;
+    case PS_TYPE_U32:
+        qsort(outVec, inN, elSize, psCompareU32);
+        break;
+    case PS_TYPE_U64:
+        qsort(outVec, inN, elSize, psCompareU64);
+        break;
+    case PS_TYPE_S8:
+        qsort(outVec, inN, elSize, psCompareS8);
+        break;
+    case PS_TYPE_S16:
+        qsort(outVec, inN, elSize, psCompareS16);
+        break;
+    case PS_TYPE_S32:
+        qsort(outVec, inN, elSize, psCompareS32);
+        break;
+    case PS_TYPE_S64:
+        qsort(outVec, inN, elSize, psCompareS64);
+        break;
+    case PS_TYPE_F32:
+        qsort(outVec, inN, elSize, psCompareF32);
+        break;
+    case PS_TYPE_F64:
+        qsort(outVec, inN, elSize, psCompareF64);
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
+    }
+
+    return outVector;
+}
+
+#define SORT_INDICES(TYPE)                                                                                   \
+for(i=0; i<inN; i++) {                                                                                       \
+    for(j=0; j<inN; j++) {                                                                                   \
+        diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]);                                             \
+        if(diff < FLT_EPSILON) {                                                                             \
+            outVec[i] = j;                                                                                   \
+            break;                                                                                           \
+        }                                                                                                    \
+    }                                                                                                        \
+}
+
+psVector* psVectorSortIndex(psVector* restrict outVector, const psVector* restrict inVector)
+{
+    int inN = 0;
+    int outN = 0;
+    int i = 0;
+    int j = 0;
+    float *inVec = NULL;
+    int *outVec = NULL;
+    double diff = 0.0f;
+    psVector* tmpVector = NULL;
+    psElemType inType = 0;
+
+    if (inVector == NULL) {
+        psError(__func__, " : Line %d - Null input vector\n", __LINE__);
+        return outVector;
+    }
+
+    inN = inVector->n;
+    inVec = inVector->data.V;
+    inType = inVector->type.type;
+
+    if (outVector == NULL) {
+        outVector = psVectorAlloc(inN, PS_TYPE_U32);
+        outVector->n = inN;
+    }
+
+    outN = outVector->n;
+    outVec = outVector->data.V;
+
+    if (inN != outN) {
+        psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",
+                __LINE__, inN, outN);
+        return outVector;
+    }
+
+    if (outVector->type.type != PS_TYPE_U32) {
+        psError(__func__, " : Line %d - Output vector is not of type U32: out=%d\n",
+                __LINE__, outVector->type.type);
+        return outVector;
+    }
+
+    tmpVector = psVectorAlloc(inN, inType);
+    tmpVector->n = inN;
+    tmpVector = psVectorSort(tmpVector, inVector);
+
+    // Sort output vector
+    switch (inType) {
+    case PS_TYPE_U8:
+        SORT_INDICES(U8);
+        break;
+    case PS_TYPE_U16:
+        SORT_INDICES(U16);
+        break;
+    case PS_TYPE_U32:
+        SORT_INDICES(U32);
+        break;
+    case PS_TYPE_U64:
+        SORT_INDICES(U64);
+        break;
+    case PS_TYPE_S8:
+        SORT_INDICES(S8);
+        break;
+    case PS_TYPE_S16:
+        SORT_INDICES(S16);
+        break;
+    case PS_TYPE_S32:
+        SORT_INDICES(S32);
+        break;
+    case PS_TYPE_S64:
+        SORT_INDICES(S64);
+        break;
+    case PS_TYPE_F32:
+        SORT_INDICES(F32);
+        break;
+    case PS_TYPE_F64:
+        SORT_INDICES(F64);
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
+    }
+
+    // Free temp memory
+    psFree(tmpVector);
+
+    return outVector;
+}
+
+static void vectorFree(psVector* restrict psVec)
+{
+    if (psVec == NULL) {
+        return;
+    }
+
+    psFree(psVec->data.V);
+}
Index: /tags/rel2_1/psLib/src/mathtypes/psVector.h
===================================================================
--- /tags/rel2_1/psLib/src/mathtypes/psVector.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/mathtypes/psVector.h	(revision 1553)
@@ -0,0 +1,133 @@
+
+/** @file  psVector.h
+ *
+ *  @brief Contains basic vector definitions and operations
+ *
+ *  This file defines the basic type for a vector struct and functions useful
+ *  in manupulating vectors.
+ *
+ *  @ingroup Vector
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:17:35 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_VECTOR_H
+#define PS_VECTOR_H
+
+#include "psType.h"
+
+/// @addtogroup Vector
+/// @{
+
+/** An vector to support primitive types.
+ *
+ * Struct for maintaining an vector of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psType type;                ///< Type of data.
+    unsigned int nalloc;        ///< Total number of elements available.
+    unsigned int n;             ///< Number of elements in use.
+
+    union {
+        psU8* U8;               ///< Unsigned 8-bit integer data.
+        psU16* U16;             ///< Unsigned 16-bit integer data.
+        psU32* U32;             ///< Unsigned 32-bit integer data.
+        psU64* U64;             ///< Unsigned 64-bit integer data.
+        psS8* S8;               ///< Signed 8-bit integer data.
+        psS16* S16;             ///< Signed 16-bit integer data.
+        psS32* S32;             ///< Signed 32-bit integer data.
+        psS64* S64;             ///< Signed 64-bit integer data.
+        psF32* F32;             ///< Single-precision float data.
+        psF64* F64;             ///< Double-precision float data.
+        psC32* C32;             ///< Single-precision complex data.
+        psC64* C64;             ///< Double-precision complex data.
+        psPTR V;                ///< Pointer to data.
+    } data;                     ///< Union for data types.
+}
+psVector;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a vector.
+ *
+ *  Uses psLib memory allocation functions to create a vector collection of 
+ *  data as defined by the psType type.
+ *
+ * @return psVector*    Pointer to psVector.
+ */
+psVector* psVectorAlloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psElemType dataType                ///< Type of data to be held by vector.
+);
+
+/** Reallocate a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection 
+ *  of data. The vector is reallocated according to the psType type member 
+ *  contained within the vector.
+ *
+ *  @return psVector*      Pointer to psVector.
+ *
+ */
+psVector* psVectorRealloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psVector* restrict psVec           ///< Vector to reallocate.
+);
+
+/** Recycle a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection 
+ *  of data. The vector is reallocated according to the psElemType type 
+ *  parameter.
+ *
+ * @return psVector*       Pointer to psVector.
+ *
+ */
+psVector* psVectorRecycle(
+    psVector* restrict psVec,
+    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
+    ///< taken to preserve the values.
+
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psElemType type                    ///< the datatype of the returned vector
+);
+
+/** Sort an array of floats.
+ *
+ *  Sorts an array of floats in ascending order.  This function is valid for
+ *  all non-complex data types.
+ *
+ *  @return  psVector*     Pointer to sorted psVector.
+ */
+psVector* psVectorSort(
+    psVector* restrict outVector,      ///< the output vector to recycle, or NULL if new vector desired.
+    const psVector* restrict inVector  ///< the vector to sort.
+);
+
+/** Creates an array of indices based on sort ordered of array.
+ *
+ *  Sorts a vector and creates an integer array holding indices of 
+ *  sorted float values based on pre-sort index positions.  
+ *
+ *  @return  psVector*     vector of the indices of sort.
+ */
+psVector* psVectorSortIndex(
+    psVector* restrict outVector,      ///< vector to recycle
+    const psVector* restrict inVector  ///< vector to sort
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/pslib.h
===================================================================
--- /tags/rel2_1/psLib/src/pslib.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/pslib.h	(revision 1553)
@@ -0,0 +1,158 @@
+
+/** @file  pslib.h
+*
+*  @brief Contains the complete list of header files for pslib.
+*
+*  This header file includes all the necessary header files for a user to
+*  user all public functions within the pslib library.
+*
+*  @author Eric Van Alst, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:40:54 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_LIB_H
+#define PS_LIB_H
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+
+// System Utilities
+
+/// @defgroup SysUtils System Utilities
+/// @{
+
+/** @defgroup MemoryManagement Memory Management Utilities
+ *
+ *  This is the generic memory management system put inbetween the user's high level code and the OS-level
+ *  memory allocation routines.  This system adds such features as callback routines for memory error events,
+ *  tracing capabilities, and reference counting.
+ *
+ *  @ingroup SysUtils
+ */
+
+#include "fitsio.h"
+
+#include "psMemory.h"
+
+/// @defgroup LogTrace Tracing and Logging
+/// @ingroup SysUtils
+#include "psLogMsg.h"
+#include "psTrace.h"
+
+/// @defgroup ErrorHandling Error Handling
+/// @ingroup SysUtils
+#include "psAbort.h"
+#include "psError.h"
+
+#include "psString.h"
+
+/// @}
+
+// Collections
+/// @defgroup DataContainer Data Containers
+/// @{
+
+#include "psType.h"
+
+/// @defgroup LinkedList Linked List
+/// @ingroup DataContainer
+#include "psList.h"
+
+/// @defgroup HashTable Hash Table
+/// @ingroup DataContainer
+#include "psHash.h"
+
+/// @defgroup Scalar Scalar
+/// @ingroup DataContainer
+#include "psScalar.h"
+
+/// @defgroup Vector Vector Container
+/// @ingroup DataContainer
+#include "psVector.h"
+
+/// @defgroup Array Array Container
+/// @ingroup DataContainer
+#include "psArray.h"
+
+/// @defgroup Image Image Container
+/// @ingroup DataContainer
+/// @{
+#include "psImage.h"
+#include "psImageExtraction.h"
+#include "psImageManip.h"
+
+/// @defgroup ImageIO Image File I/O Functions
+/// @ingroup Image
+#include "psImageIO.h"
+
+/// @defgroup ImageStats Image Statistical Functions
+/// @ingroup Image
+#include "psImageStats.h"
+
+/// @}
+
+/// @defgroup BitSet Bit Set Container
+/// @ingroup DataContainer
+#include "psBitSet.h"
+
+/// @}
+
+// Data Manipulation
+/// @defgroup DataManip Data Manipulation
+/// @{
+
+/// @defgroup Compare Comparison Functions
+/// @ingroup DataManip
+#include "psCompare.h"
+
+/// @defgroup Stats Statistic Functions
+/// @ingroup DataManip
+#include "psStats.h"
+
+/// @defgroup Matrix Matrix Operations
+/// @ingroup DataManip
+#include "psMatrix.h"
+
+/// @defgroup MatrixVectorArithmetic Matrix Vector Arithmetic Operations
+/// @ingroup DataManip
+#include "psMatrixVectorArithmetic.h"
+
+/// @defgroup Transform Fourier Transform Operations
+/// @ingroup DataManip
+#include "psFFT.h"
+
+#include "psFunctions.h"
+#include "psMinimize.h"
+
+/// @}
+
+// Astronomy
+/// @defgroup Astronomy Astronomy Functions
+/// @{
+
+/// @defgroup CoordinateTransform Coordinate Functions
+/// @ingroup Astronomy
+#include "psCoord.h"
+
+/// @defgroup Photometry Photometry
+/// @ingroup Astronomy
+#include "psPhotometry.h"
+
+/// @defgroup Time Time Functions
+/// @ingroup Astronomy
+#include "psTime.h"
+
+/// @defgroup Metadata Metadata Functions
+/// @ingroup Astronomy
+#include "psMetadata.h"
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psAbort.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psAbort.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psAbort.c	(revision 1553)
@@ -0,0 +1,89 @@
+
+/** @file  psAbort.c
+ *
+ *  @brief Contains the definition for abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdarg.h>
+#include <stdlib.h>
+#include "psAbort.h"
+#include "psLogMsg.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+void psAbort(const char *name, const char *fmt, ...)
+{
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    // Call logging function with PS_LOG_ABORT level
+    psLogMsgV(name, PS_LOG_ABORT, fmt, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    // Call system abort function to terminate program execution
+    abort();
+}
Index: /tags/rel2_1/psLib/src/sys/psAbort.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psAbort.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psAbort.h	(revision 1553)
@@ -0,0 +1,47 @@
+
+/** @file  psAbort.h
+ *
+ *  @brief Contains the declarations for the abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @ingroup ErrorHandling
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ABORT_H
+#define PS_ABORT_H
+
+// Doxygen grouping tags
+
+/** @addtogroup ErrorHandling
+ *  @{
+ */
+
+/** Reports an abort message to logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of 
+ *  PS_LOG_ABORT and pass the parameters name and fmt to generate a proper
+ *  log message.  After logging, this function will call system abort 
+ *  function to abnormally terminate the program.
+ *
+ *  @return  void No return value
+ *
+ */
+void psAbort(
+    const char *name,                  ///< Source of abort such as file or function detected
+    const char *fmt,                   ///< A printf style formatting statement defining msg
+    ...
+);
+
+/* @} */// Doxygen - End of SystemGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psError.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psError.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psError.c	(revision 1553)
@@ -0,0 +1,86 @@
+
+/** @file  psError.c
+ *
+ *  @brief Contains the definitions for the error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdarg.h>
+#include "psLogMsg.h"
+#include "psError.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATIONS - LOCAL                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATIONS - PUBLIC                                         */
+
+/*****************************************************************************/
+
+void psError(const char *name, const char *fmt, ...)
+{
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    // Call logging function with PS_LOG_ERROR level
+    psLogMsgV(name, PS_LOG_ERROR, fmt, argPtr);
+
+    // Clean up stack after variable argument has been used
+    va_end(argPtr);
+}
Index: /tags/rel2_1/psLib/src/sys/psError.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psError.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psError.h	(revision 1553)
@@ -0,0 +1,43 @@
+
+/** @file  psError.h
+ *
+ *  @brief Contains the declarations for the error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @ingroup ErrorHandling
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ERROR_H
+#define PS_ERROR_H
+
+/** @addtogroup ErrorHandling
+ *  @{
+ */
+
+/** Reports an error message to the logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
+ *  log message.
+ *
+ */
+void psError(
+    const char *name,                  ///< Source of error such as file or function detected
+    const char *fmt,                   ///< A printf style formatting statement defining msg
+    ...
+);
+
+/* @} */// End of SysUtils Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psLogMsg.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psLogMsg.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psLogMsg.c	(revision 1553)
@@ -0,0 +1,365 @@
+
+/** @file  psLogMsg.c
+ *  @brief Procedures for logging messages.
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedure which set
+ *  message log levels, messahe log formats, message log destinations, and
+ *  for generating the messages themselves.
+ *  @ingroup LogTrace
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************
+NOTES: currently, the prototype code has the following global variables:
+    static int p_psGlobalLogDest;
+    static int p_psGlobalLogLevel;
+    static int p_psLogTime;
+    static int p_psLogHost;
+    static int p_psLogLevel;
+    static int p_psLogName;
+    static int p_psLogMsg;
+ *****************************************************************************/
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psTrace.h"
+
+#define MIN_LOG_LEVEL 0
+#define MAX_LOG_LEVEL 9
+
+#define MAX_LOG_LINE_LENGTH 128
+static FILE *logDest = (FILE *) 1;      // flag to initialize to stderr before using.
+static int globalLogLevel = PS_LOG_INFO;        // log all messages at this or above
+static bool logTime = true;     // Flag to include time info
+static bool logHost = true;     // Flag to include host info
+static bool logLevel = true;    // Flag to include level info
+static bool logName = true;     // Flag to include name info
+static bool logMsg = true;      // Flag to include message info
+
+/*****************************************************************************
+psLogSetLevel(): Set the current log level and return old level.
+Input:
+ level (int): the new log level.
+Output:
+ none
+Return:
+ The old log level.
+ *****************************************************************************/
+int psLogSetLevel(int level)
+{
+    // Save old global log level for changing it.
+    int oldLevel = globalLogLevel;
+
+    if ((level < MIN_LOG_LEVEL) || (level > MAX_LOG_LEVEL)) {
+        psLogMsg("logmsg", PS_LOG_WARN, "Attempt to set invalid logMsg level: %d", level);
+        level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
+    }
+    // Set new global log level
+    globalLogLevel = level;
+
+    // Return old global log level
+    return oldLevel;
+}
+
+/*****************************************************************************
+psLogSetDestination(): sets the destination where log messages will be
+sent to.
+ 
+Input:
+ dest (int): the new log destination
+Output:
+ None.
+Return:
+ An integer specifying the old log destination.
+ *****************************************************************************/
+bool psLogSetDestination(const char *dest)
+{
+    char protocol[5];
+    char location[257];
+
+    // if logDest has not been initialized, do so before using it
+    if (logDest == (FILE *) 1) {
+        logDest = stderr;
+    }
+
+    if (dest == NULL || strcmp(dest, "none") == 0) {
+        if (logDest != NULL && logDest != stderr && logDest != stdout) {
+            fclose(logDest);
+        }
+        logDest = NULL;
+        return true;
+    }
+
+    if (sscanf(dest, "%4s:%256s", protocol, location) < 2) {
+        psError(__func__, "The specified destination, %s, is malformed.", dest);
+        return false;
+    }
+
+    if (strcmp(protocol, "dest") == 0) {
+        if (strcmp(location, "stderr") == 0) {
+            if (logDest != NULL && logDest != stderr && logDest != stdout) {
+                fclose(logDest);
+            }
+            logDest = stderr;
+            return true;
+        }
+        if (strcmp(location, "stdout") == 0) {
+            if (logDest != NULL && logDest != stderr && logDest != stdout) {
+                fclose(logDest);
+            }
+            logDest = stdout;
+            return true;
+        }
+        psError(__func__, "The location, %s, for protocol 'dest' is invalid.", location);
+        return 1;
+    } else if (strcmp(protocol, "file") == 0) {
+        FILE *file = fopen(location, "w");
+
+        if (file == NULL) {
+            psError(__func__, "Could not open file '%s' for output.", location);
+            return false;
+        }
+        if (logDest != NULL && logDest != stderr && logDest != stdout) {
+            fclose(logDest);
+        }
+        logDest = file;
+        return true;
+    }
+
+    psError(__func__, "Do not know how to handle the protocol '%s'.", protocol);
+    return false;
+}
+
+/*****************************************************************************
+psLogSetFormat(): Set the format of psLogMsg output.  More precisely,
+    provide a string consisting of the letters {H (host), L (level), M
+    (message), N (name), T (time)}.  The default is "HLMNT".  This string
+    determines whether or not they associated type of information will be
+    included in message logs.  It does not determine the order in which that
+    information will appear (that order is fixed).
+ 
+Input:
+    fmt: a string specifying the format.
+Output:
+    none.
+Return:
+    NULL.
+ *****************************************************************************/
+void psLogSetFormat(const char *fmt)
+{
+    // assume nothing desired unless specified
+    logHost = false;
+    logLevel = false;
+    logMsg = false;
+    logName = false;
+    logTime = false;
+
+    // if fmt is NULL, no logging is desired.
+    if (fmt == NULL) {
+        return;
+    }
+
+    if (strlen(fmt) == 0) {
+        fmt = "THLNM";
+    }
+    // Step through each character in the format string.  For each letter
+    // in that string, set/unset the appropriate logging.
+
+    for (const char *ptr = fmt; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            logHost = true;
+            break;
+        case 'L':
+        case 'l':
+            logLevel = true;
+            break;
+        case 'M':
+        case 'm':
+            logMsg = true;
+            break;
+        case 'N':
+        case 'n':
+            logName = true;
+            break;
+        case 'T':
+        case 't':
+            logTime = true;
+            break;
+        default:
+            psError(__func__, "Unknown logging keyword %c", *ptr);
+            break;
+        }
+    }
+
+    if (!logMsg) {
+        psTrace("utils.logMsg", 1, "You must at least log error messages (You chose \"%s\")", fmt);
+    }
+}
+
+#if !defined(HOST_NAME_MAX)                // should be in limits.h
+#define HOST_NAME_MAX 256
+#endif
+
+/*****************************************************************************
+    psVLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name
+ level
+ fmt
+ ap
+    Output:
+ none
+    Return:
+ NULL.
+ *****************************************************************************/
+void psLogMsgV(const char *name, int level, const char *fmt, va_list ap)
+{
+    static int first = 1;       // Flag for calling gethostname()
+    static char hostname[HOST_NAME_MAX + 1];
+
+    // Buffer for hostname.
+    char clevel = 0;            // letter-name for level
+    char head[MAX_LOG_LINE_LENGTH + 2]; // the added two are for the ending | and \0
+    char *head_ptr = head;      // where we've got to in head
+    int maxLength = MAX_LOG_LINE_LENGTH;
+    time_t clock = time(NULL);  // The current time.
+    struct tm *utc = gmtime(&clock);    // The current gm time.
+
+    // if logDest has not been initialized, do so before using it
+    if (logDest == (FILE *) 1) {
+        logDest = stderr;
+    }
+    // If logging is off, or if the level is too high, return immediately.
+    if ((level > globalLogLevel) || (logDest == NULL)) {
+        return;
+    }
+    // If I have not been here yet, determine my hostname and save it.
+    if (first) {
+        first = 0;
+        gethostname(hostname, HOST_NAME_MAX);
+    }
+
+    switch (level) {
+    case PS_LOG_ABORT:
+        clevel = 'A';
+        break;
+
+    case PS_LOG_ERROR:
+        clevel = 'E';
+        break;
+
+    case PS_LOG_WARN:
+        clevel = 'W';
+        break;
+
+    case PS_LOG_INFO:
+        clevel = 'I';
+        break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        clevel = level + '0';
+        break;
+
+    default:
+        psTrace("utils.logMsg", 2, "Invalid logMsg level: %d (%s)\n", level, fmt);
+        level = (level < 0) ? 0 : 9;
+        break;
+    }
+
+    // Create the various log fields...
+    if (logTime) {
+        maxLength -= snprintf(head_ptr, maxLength, "%4d:%02d:%02d %02d:%02d:%02dZ",
+                              utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                              utc->tm_hour, utc->tm_min, utc->tm_sec) - 1;
+        head_ptr += strlen(head_ptr);
+    }
+    // Hostname should be 20 characters.
+    if (logHost) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%-20s", hostname);
+        head_ptr += strlen(head_ptr);
+    }
+    if (logLevel) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%c", clevel);
+        head_ptr += strlen(head_ptr);
+    }
+    // The name field must be 15 characters.
+    if (logName) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%15.15s", name);
+        head_ptr += strlen(head_ptr);
+    }
+
+    if (head_ptr > head) {
+        *head_ptr++ = '|';
+    } else if (!logMsg) {                  // no output desired
+        return;
+    }
+    *head_ptr = '\0';
+
+    fputs(head, logDest);
+    if (logMsg) {
+        vfprintf(logDest, fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            fputc('\n', logDest);
+        }
+    } else {
+        fputc('\n', logDest);
+    }
+}
+
+/*****************************************************************************
+    psLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name: Indicates the source of this log message.
+ level: The severity of this log message.
+ fmt: The printf-stype formatted string, followed by the arguments
+  to that string.
+ ... The arguments to the above printf-style string.
+    Output:
+ none
+    Return:
+ NULL
+ *****************************************************************************/
+void psLogMsg(const char *name, int level, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    psLogMsgV(name, level, fmt, ap);
+    va_end(ap);
+}
Index: /tags/rel2_1/psLib/src/sys/psLogMsg.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psLogMsg.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psLogMsg.h	(revision 1553)
@@ -0,0 +1,104 @@
+
+/** @file  psLogMsg.h
+ *  @brief Procedures for logging messages.
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedure which set
+ *  message log levels, messahe log formats, message log destinations, and
+ *  for generating the messages themselves.
+ *  @ingroup LogTrace
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_LOG_MSG_H)
+#define PS_LOG_MSG_H
+#include <stdarg.h>
+#include <stdbool.h>
+
+/** @addtogroup LogTrace
+ *  @{
+ */
+
+/** This procedure sets the destination for future log messages.  Currently
+ *  the destination is specified by an integer which can have the following
+ *  pre-defined values: PS_LOG_NONE, PS_LOG_TO_STDOUT, and PS_LOG_TO_STDERR.
+ *  In future versions, this procedure will take a character string as an
+ *  argument which can specify more general log destinations.
+ *
+ *  @return int     true if set successfully, otherwise false.
+ */
+bool psLogSetDestination(
+    const char *dest                   ///< Specifies where to send messages.
+);
+
+/** This procedure sets the message level for future log messages.  Subsequent
+ *  log messages, with a log level of "mylevel", will only be logged if
+ *  "mylevel" is less than the current log level set by this procedure.
+ *  Ie. higher values set by this procedure will cause more log messages to
+ *  be displayed.
+ *
+ *  @return int    old logging level
+ */
+int psLogSetLevel(
+    int level                          ///< Specifies the system log level
+);
+
+/** This procedure sets the log format for future log messages.  The argument
+ *  must be a character string consistsing of the letters H (host), L
+ *  (level), M (message), N (name), and T (time).  The default is "THLNM".
+ *  Deleting a letter from the string will cause the associated information
+ *  to not be logged.
+ *
+ */
+void psLogSetFormat(
+    const char *fmt                    ///< Specifies the system log format
+);
+
+/** This procedure logs a message to the destination set by a prior
+ *  call to psLogSetDestination(), if myLevel is less than the level
+ *  specified by a prior call to psLogSetLevel().  The message is specified
+ *  with a printf-stype string an arguments.
+ *
+ */
+void psLogMsg(
+    const char *name,                  ///< name of the log source
+    int myLevel,                       ///< severity level of this log message
+    const char *fmt,                   ///< printf-style format command
+    ...
+);
+
+/** This procedure is functionally equivalent to psLogMsg(), except that
+ *  it takes a va_list as the message parameter, not a printf-style string.
+ *
+ */
+void psLogMsgV(
+    const char *name,                  ///< name of the log source
+    int myLevel,                       ///< severity level of this log message
+    const char *fmt,                   ///< printf-style format command
+    va_list ap                         ///< varargs argument list
+);
+
+///< Status codes for log messages
+enum {
+    PS_LOG_ABORT = 0,                  ///< log message is a critical error, perform an abort after printing
+    PS_LOG_ERROR,                      ///< log message is an error, but don't abort
+    PS_LOG_WARN,                       ///< log message is a warning
+    PS_LOG_INFO                        ///< log message is informational only
+};
+
+///< Destinations for log messages
+enum {
+    PS_LOG_NONE,                       ///< turn off logging
+    PS_LOG_TO_STDERR,                  ///< log to system's stderr
+    PS_LOG_TO_STDOUT                   ///< log to system's stdout
+};
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psMemory.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psMemory.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psMemory.c	(revision 1553)
@@ -0,0 +1,631 @@
+
+/** @file  psMemory.c
+*
+*  @brief Contains the definitions for the memory management system
+*
+*  psMemory.h has additional information and documentation of the routines found in this file.
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Robert Lupton, Princeton University
+*
+*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#define PS_ALLOW_MALLOC                    // we're allowed to call malloc()
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psLogMsg.h"
+
+#define P_PS_MEMMAGIC (void *)0xdeadbeef   // Magic number in psMemBlock header
+
+#define P_PS_LARGE_BLOCK_SIZE 65536        // size where under, we try to recycle
+
+static int checkMemBlock(const psMemBlock* m, const char *funcName);
+static psMemBlock* lastMemBlockAllocated = NULL;
+static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int recycleBins = 13;
+static int recycleBinSize[14] = {
+                                    8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE
+                                };
+
+// N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops)
+static psMemBlock* recycleMemBlockList[13] = {
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+        };
+
+#ifdef PS_MEM_DEBUG
+static psMemBlock* deadBlockList;       // a place to put dead memBlocks in debug mode.
+#endif
+
+/**
+ * Unique ID for allocated blocks
+ */
+static psMemoryId memid = 0;
+
+/**
+ *  Default memExhausted callback.
+ */
+static void *memExhaustedCallbackDefault(size_t size)
+{
+    void *ptr = NULL;
+
+    pthread_mutex_lock(&recycleMemBlockListMutex);
+    int level = recycleBins - 1;
+
+    while (level >= 0 && ptr == NULL) {
+        while (recycleMemBlockList[level] != NULL && ptr == NULL) {
+            psMemBlock* old = recycleMemBlockList[level];
+
+            recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;
+            free(old);
+            ptr = malloc(size);
+        }
+        level--;
+    }
+    pthread_mutex_unlock(&recycleMemBlockListMutex);
+
+    return ptr;
+}
+
+static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault;
+
+psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func)
+{
+    psMemExhaustedCallback old = memExhaustedCallback;
+
+    if (func != NULL) {
+        memExhaustedCallback = func;
+    } else {
+        memExhaustedCallback = memExhaustedCallbackDefault;
+    }
+
+    return old;
+}
+
+static void memProblemCallbackDefault(const psMemBlock* ptr, const char *file, int lineno)
+{
+    if (ptr->refCounter < 1) {
+        psError(__func__,
+                "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
+                ptr->id, ptr->file, ptr->lineno, file, lineno);
+    }
+
+    if (lineno > 0) {
+        psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);
+    }
+}
+static psMemProblemCallback memProblemCallback = memProblemCallbackDefault;
+
+psMemProblemCallback psMemProblemCallbackSet(psMemProblemCallback func)
+{
+    psMemProblemCallback old = memProblemCallback;
+
+    if (func != NULL) {
+        memProblemCallback = func;
+    } else {
+        memProblemCallback = memProblemCallbackDefault;
+    }
+
+    return old;
+}
+
+/*
+ * And now the I-want-to-be-informed callbacks
+ *
+ * Call the callbacks when these IDs are allocated/freed
+ */
+psMemoryId p_psMemAllocateID = 0;       // notify user this block is allocated
+psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
+
+psMemoryId psMemAllocateCallbackSetID(psMemoryId id)
+{
+    psMemoryId old = p_psMemAllocateID;
+
+    p_psMemAllocateID = id;
+
+    return old;
+}
+
+psMemoryId psMemFreeCallbackSetID(psMemoryId id)
+{
+    psMemoryId old = p_psMemFreeID;
+
+    p_psMemFreeID = id;
+
+    return old;
+}
+
+/*
+ * Default callback for both allocate and free. Note that the
+ * value of p_psMemAllocateID/p_psMemFreeID is incremented
+ * by the return value (so returning 0 means that the callback
+ * isn't resignalled)
+ */
+static psMemoryId memAllocateCallbackDefault(const psMemBlock* ptr)
+{
+    static psMemoryId incr = 0; // "p_psMemAllocateID += incr"
+
+    return incr;
+}
+
+static psMemoryId memFreeCallbackDefault(const psMemBlock* ptr)
+{
+    static psMemoryId incr = 0; // "p_psMemFreeID += incr"
+
+    return incr;
+}
+
+/*
+ * The default callbacks, and the routines to change them
+ */
+static psMemAllocateCallback memAllocateCallback = memAllocateCallbackDefault;
+static psMemFreeCallback memFreeCallback = memFreeCallbackDefault;
+
+psMemAllocateCallback psMemAllocateCallbackSet(psMemAllocateCallback func)
+{
+    psMemFreeCallback old = memAllocateCallback;
+
+    if (func != NULL) {
+        memAllocateCallback = func;
+    } else {
+        memAllocateCallback = memAllocateCallbackDefault;
+    }
+
+    return old;
+}
+
+psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func)
+{
+    psMemFreeCallback old = memFreeCallback;
+
+    if (func != NULL) {
+        memFreeCallback = func;
+    } else {
+        memFreeCallback = memFreeCallbackDefault;
+    }
+
+    return old;
+}
+
+/*
+ * Return memory ID counter for next block to be allocated
+ */
+psMemoryId psMemGetId(void)
+{
+    psMemoryId id;
+
+    pthread_mutex_lock(&memIdMutex);
+    id = memid + 1;
+    pthread_mutex_unlock(&memIdMutex);
+
+    return id;
+}
+
+/*
+ * Routines to check the consistency of the allocated and/or free memory arena
+ *
+ * N.b. If the block wasn't allocated by psAlloc, it will appear corrupted
+ */
+
+static int checkMemBlock(const psMemBlock* m, const char *funcName)
+{
+    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
+    // we shouldn't call such things as p_psAlloc/p_psFree here.
+
+    if (m == NULL) {
+        psError(funcName, "Memory Corruption: NULL memory block found.");
+        return 1;
+    }
+
+    if (m->refCounter == 0) {
+        // using an unreferenced block of memory, are you?
+        psError(__func__, "Memory Corruption: memory block %ld was freed but still used.", m->id);
+        return 1;
+    }
+
+    if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
+        psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)", m->id);
+        return 1;
+    }
+    if (*(void **)((int8_t *) (m + 1) + m->userMemorySize) != P_PS_MEMMAGIC) {
+        psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", m->id);
+        return 1;
+    }
+
+    return 0;
+}
+
+int psMemCheckCorruption(bool abort_on_error)
+{
+    int nbad = 0;               // number of bad blocks
+
+    // get exclusive access to the memBlock list to avoid it changing on us while we use it.
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock) {
+        if (checkMemBlock(iter, __func__)) {
+            nbad++;
+
+            memProblemCallback(iter, __func__, __LINE__);
+
+            if (abort_on_error) {
+                // release the lock on the memblock list
+                pthread_mutex_unlock(&memBlockListMutex);
+                psAbort(__func__, "Detected memory corruption");
+                return nbad;
+            }
+        }
+    }
+
+    // release the lock on the memblock list
+    pthread_mutex_unlock(&memBlockListMutex);
+    return nbad;
+}
+
+void *p_psAlloc(size_t size, const char *file, int lineno)
+{
+
+    psMemBlock* ptr = NULL;
+
+    // memory is of the size I want to bother recycling?
+    if (size < P_PS_LARGE_BLOCK_SIZE) {
+        // find the bin we need.
+        int level = 0;
+
+        while (size > recycleBinSize[level]) {
+            level++;
+        }
+        // Are we in one of the bins
+        if (level < recycleBins) {
+
+            size = recycleBinSize[level];  // round-up size to next sized bin.
+
+            pthread_mutex_lock(&recycleMemBlockListMutex);
+
+            if (recycleMemBlockList[level] != NULL) {
+                ptr = recycleMemBlockList[level];
+                recycleMemBlockList[level] = ptr->nextBlock;
+                if (recycleMemBlockList[level] != NULL) {
+                    recycleMemBlockList[level]->previousBlock = NULL;
+                }
+                size = ptr->userMemorySize;
+            }
+
+            pthread_mutex_unlock(&recycleMemBlockListMutex);
+        }
+    }
+
+    if (ptr == NULL) {
+        ptr = malloc(sizeof(psMemBlock) + size + sizeof(void *));
+
+        if (ptr == NULL) {
+            ptr = memExhaustedCallback(size);
+            if (ptr == NULL) {
+                psAbort(__func__, "Failed to allocate %u bytes at %s:%d", size, file, lineno);
+            }
+        }
+
+        ptr->startblock = P_PS_MEMMAGIC;
+        ptr->endblock = P_PS_MEMMAGIC;
+        ptr->userMemorySize = size;
+        pthread_mutex_init(&ptr->refCounterMutex, NULL);
+    }
+    // increment the memory id safely.
+    pthread_mutex_lock(&memBlockListMutex);
+    *(psMemoryId* ) & ptr->id = ++memid;
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    ptr->file = file;
+    ptr->freeFcn = NULL;
+    *(unsigned int *)&ptr->lineno = lineno;
+    *(void **)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
+    ptr->previousBlock = NULL;
+
+    ptr->refCounter = 1;                   // one user so far
+
+    // need exclusive access of the memory block list now...
+    pthread_mutex_lock(&memBlockListMutex);
+
+    // insert the new block to the front of the memBlock linked-list
+    ptr->nextBlock = lastMemBlockAllocated;
+    if (ptr->nextBlock != NULL) {
+        ptr->nextBlock->previousBlock = ptr;
+    }
+    lastMemBlockAllocated = ptr;
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    // Did the user ask to be informed about this allocation?
+    if (ptr->id == p_psMemAllocateID) {
+        p_psMemAllocateID += memAllocateCallback(ptr);
+    }
+    // And return the user the memory that they allocated
+    return ptr + 1;                        // user memory
+}
+
+void *p_psRealloc(void *vptr, size_t size, const char *file, int lineno)
+{
+    if (vptr == NULL) {
+        return p_psAlloc(size, file, lineno);
+    } else {
+        psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+        bool isBlockLast = false;
+
+        if (checkMemBlock(ptr, __func__) != 0) {
+            memProblemCallback(ptr, file, lineno);
+            psAbort(file, "Realloc detected a memory corruption (id %ld @ %s:%d).",
+                    ptr->id, ptr->file, ptr->lineno);
+        }
+
+        pthread_mutex_lock(&memBlockListMutex);
+
+        isBlockLast = (ptr == lastMemBlockAllocated);
+
+        ptr = (psMemBlock* ) realloc(ptr, sizeof(psMemBlock) + size + sizeof(void *));
+
+        if (ptr == NULL) {
+            psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d", size, file, lineno);
+        }
+
+        ptr->userMemorySize = size;
+        *(void **)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
+
+        if (isBlockLast) {
+            lastMemBlockAllocated = ptr;
+        }
+        // the block location may have changed, so fix the linked list addresses.
+        if (ptr->nextBlock != NULL) {
+            ptr->nextBlock->previousBlock = ptr;
+        }
+        if (ptr->previousBlock != NULL) {
+            ptr->previousBlock->nextBlock = ptr;
+        }
+
+        pthread_mutex_unlock(&memBlockListMutex);
+
+        // Did the user ask to be informed about this allocation?
+        if (ptr->id == p_psMemAllocateID) {
+            p_psMemAllocateID += memAllocateCallback(ptr);
+        }
+
+        return ptr + 1;                    // usr memory
+    }
+}
+
+void p_psFree(void *vptr, const char *file, int lineno)
+{
+    (void)p_psMemDecrRefCounter(vptr, file, lineno);    // this handles the free, if required.
+}
+
+/*
+ * Check for memory leaks.
+ */
+int psMemCheckLeaks(psMemoryId id0, psMemBlock* ** arr, FILE * fd)
+{
+    int nleak = 0;
+    int j = 0;
+    psMemBlock* topBlock = lastMemBlockAllocated;
+
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
+        if ((psMemGetRefCounter(iter + 1) > 0) && (iter->id >= id0)) {
+            nleak++;
+
+            if (fd != NULL) {
+                if (nleak == 1) {
+                    fprintf(fd, "   %20s:line ID\n", "file");
+                }
+
+                fprintf(fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);
+            }
+        }
+    }
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    if (nleak == 0 || arr == NULL) {
+        return nleak;
+    }
+
+    *arr = p_psAlloc(nleak * sizeof(psMemBlock), __FILE__, __LINE__);
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
+        if ((psMemGetRefCounter(iter + 1) > 0) && (iter->id >= id0)) {
+            (*arr)[j++] = iter;
+            if (j == nleak) {              // found them all
+                break;
+            }
+        }
+    }
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    return nleak;
+}
+
+/*
+ * Reference counting APIs
+ */
+// return refCounter
+psReferenceCount psMemGetRefCounter(void *vptr)
+{
+    psMemBlock* ptr;
+    unsigned int refCount;
+
+    if (vptr == NULL) {
+        return 0;
+    }
+
+    ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+    refCount = ptr->refCounter;
+    pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    return refCount;
+}
+
+// increment and return refCounter
+void *p_psMemIncrRefCounter(void *vptr, const char *file, int lineno)
+{
+    psMemBlock* ptr;
+
+    if (vptr == NULL) {
+        return vptr;
+    }
+
+    ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__)) {
+        memProblemCallback(ptr, file, lineno);
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+    ptr->refCounter++;
+    pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    return vptr;
+}
+
+// decrement and return refCounter
+void *p_psMemDecrRefCounter(void *vptr, const char *file, int lineno)
+{
+    if (vptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, file, lineno);
+        return NULL;
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+
+    if (ptr->refCounter > 1) {
+        // / XXX - Probably should have another mutex here.
+        ptr->refCounter--;                 // multiple references, just decrement the count.
+        pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    } else {
+        pthread_mutex_unlock(&ptr->refCounterMutex);
+
+        // Did the user ask to be informed about this deallocation?
+        if (ptr->id == p_psMemFreeID) {
+            p_psMemFreeID += memFreeCallback(ptr);
+        }
+
+        if (ptr->freeFcn != NULL) {
+            ptr->freeFcn(vptr);
+        }
+
+        pthread_mutex_lock(&memBlockListMutex);
+
+        // cut the memBlock out of the memBlock list
+        if (ptr->nextBlock != NULL) {
+            ptr->nextBlock->previousBlock = ptr->previousBlock;
+        }
+        if (ptr->previousBlock != NULL) {
+            ptr->previousBlock->nextBlock = ptr->nextBlock;
+        }
+        if (lastMemBlockAllocated == ptr) {
+            lastMemBlockAllocated = ptr->nextBlock;
+        }
+
+        pthread_mutex_unlock(&memBlockListMutex);
+
+        // do we need to recycle?
+        if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) {
+
+            int level = 1;
+
+            while (ptr->userMemorySize >= recycleBinSize[level]) {
+                level++;
+            }
+            level--;
+
+            ptr->refCounter = 0;
+            ptr->previousBlock = NULL;
+
+            pthread_mutex_lock(&recycleMemBlockListMutex);
+            ptr->nextBlock = recycleMemBlockList[level];
+            if (recycleMemBlockList[level] != NULL) {
+                recycleMemBlockList[level]->previousBlock = ptr;
+            }
+            recycleMemBlockList[level] = ptr;
+            pthread_mutex_unlock(&recycleMemBlockListMutex);
+
+        } else {
+            // memory is larger than I want to recycle.
+            #ifdef PS_MEM_DEBUG
+            (void)p_psRealloc(vptr, 0, file, lineno);
+            ptr->previousBlock = NULL;
+            ptr->nextBlock = deadBlockList;
+            if (deadBlockList != NULL) {
+                deadBlockList->previous = ptr;
+            }
+            deadBlockList = ptr;
+            #else
+
+            pthread_mutex_destroy(&ptr->refCounterMutex);
+            free(ptr);
+            #endif
+
+        }
+
+        vptr = NULL;                       // since we freed it, make sure we return NULL.
+    }
+
+    return vptr;
+}
+
+void p_psMemSetDeallocator(void *vptr, psFreeFcn freeFcn)
+{
+    if (vptr == NULL) {
+        return;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    ptr->freeFcn = freeFcn;
+
+}
+psFreeFcn p_psMemGetDeallocator(void *vptr)
+{
+    if (vptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    return ptr->freeFcn;
+}
Index: /tags/rel2_1/psLib/src/sys/psMemory.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psMemory.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psMemory.h	(revision 1553)
@@ -0,0 +1,393 @@
+/** @file  psMemory.h
+ *
+ *  @brief Contains the definitions for the memory management system
+ *
+ *  This is the generic memory management system put inbetween the user's high level code and the OS-level
+ *  memory allocation routines.  This system adds such features as callback routines for memory error events,
+ *  tracing capabilities, and reference counting.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Robert Lupton, Princeton University
+ *
+ *  @ingroup MemoryManagement
+ *
+ *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#if !defined(PS_MEMORY_H)
+#define PS_MEMORY_H
+
+#include <stdio.h>                     // needed for FILE
+#include <stdbool.h>
+#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
+
+/** @addtogroup MemoryManagement
+ *  @{
+ */
+
+/**
+ *  @addtogroup memCallback Memory Callbacks
+ *
+ *  Routines dealing with the creating and setting of memory management callback functions.
+ */
+
+/**
+ *  @addtogroup memTracing Memory Tracing
+ *
+ *  Routines dealing with memory tracing and corruption checking.
+ */
+
+/**
+ *  @addtogroup memRefCount Reference Count
+ *
+ *  Routines dealing with the reference counting of allocated buffers.
+ */
+
+/// typedef for memory identification numbers.  Guaranteed to be some variety of integer.
+typedef unsigned long psMemoryId;
+
+/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
+typedef unsigned long psReferenceCount;
+
+/// typedef for deallocator.
+typedef void (*psFreeFcn) (void *ptr);
+
+/** Book-keeping data for storage allocator.
+ *  N.b. sizeof(psMemBlock) must be chosen such that if ptr is a pointer
+ *  returned by malloc, then ((char *)ptr + sizeof(psMemBlock)) is properly
+ *  aligned for all storage types.
+ */
+typedef struct psMemBlock
+{
+    const void *startblock;            ///< initialised to p_psMEMMAGIC
+    struct psMemBlock* previousBlock;  ///< previous block in allocation list
+    struct psMemBlock* nextBlock;      ///< next block allocation list
+    psFreeFcn freeFcn;                 ///< deallocator.  If NULL, use generic deallocation.
+    size_t userMemorySize;             ///< the size of the user-portion of the memory block
+    const psMemoryId id;               ///< a unique ID for this allocation
+    const char *file;                  ///< set from __FILE__ in e.g. p_psAlloc
+    const int lineno;                  ///< set from __LINE__ in e.g. p_psAlloc
+    pthread_mutex_t refCounterMutex;   ///< mutex to ensure exclusive access to reference counter
+    psReferenceCount refCounter;       ///< how many times pointer is referenced
+    const void *endblock;              ///< initialised to p_psMEMMAGIC
+}
+psMemBlock;
+
+/** prototype of a basic callback used by memory functions
+ *
+ *  @see psMemAllocateCallbackSet
+ *  @ingroup memCallback
+ */
+typedef psMemoryId(*psMemAllocateCallback) (
+    const psMemBlock* ptr              ///< the psMemBlock just allocated
+);
+
+/** prototype of memory free callback used by memory functions
+ *
+ *  @see psMemFreeCallbackSet
+ *  @ingroup memCallback
+ */
+typedef psMemoryId(*psMemFreeCallback) (
+    const psMemBlock* ptr              ///< the psMemBlock being freed
+);
+
+/** prototype of a callback used in error conditions
+ *
+ *  This callback should not try to call psAlloc or psFree.
+ *
+ *  @see psMemProblemCallbackSet
+ *  @ingroup memCallback
+ */
+typedef void (*psMemProblemCallback) (
+    const psMemBlock* ptr,             ///< the pointer to the problematic memory block.
+    const char *file,                  ///< the file in which the problem originated
+    int lineno                         ///< the line number in which the problem originated
+);
+
+/** prototype of a callback function used when memory runs out
+ *
+ *  @return void* pointer to requested buffer of the size size_t, or NULL if memory could not
+ *          be found.
+ *
+ *  @see psMemExhaustedCallbackSet
+ *  @ingroup memCallback
+ */
+typedef void *(*psMemExhaustedCallback) (
+    size_t size                        ///< the size of buffer required
+);
+
+/** Memory allocation.  This operates much like malloc(), but is guaranteed to return a non-NULL value.
+ *
+ *  @return void* pointer to the allocated buffer. This will not be NULL.
+ *  @see psFree 
+ */
+#ifdef DOXYGEN
+void *psAlloc(size_t size       ///< Size required
+             );
+#else
+
+void *p_psAlloc(size_t size,    ///< Size required
+                const char *file,       ///< File of call
+                int lineno      ///< Line number of call
+               );
+
+void p_psMemSetDeallocator(void *ptr, psFreeFcn freeFcn);
+psFreeFcn p_psMemGetDeallocator(void *ptr);
+
+/// Memory allocation. psAlloc sends file and line number to p_psAlloc.
+#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
+#endif
+
+/** Memory re-allocation.  This operates much like realloc(), but is guaranteed to return a non-NULL value.
+ *
+ *  @return void* pointer to resized buffer. This will not be NULL.
+ *  @see psAlloc, psFree
+ */
+#ifdef DOXYGEN
+void *psRealloc(
+    void *ptr                          ///< Pointer to re-allocate
+    size_t size,                       ///< Size required
+);
+#else
+
+void *p_psRealloc(
+    void *ptr,                         ///< Pointer to re-allocate
+    size_t size,                       ///< Size required
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+/// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
+#define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
+
+#endif
+
+/** Free memory.  This operates much like free().
+ *
+ *  @see psAlloc, psRealloc
+ */
+#ifdef DOXYGEN
+void psFree(
+    void *ptr,                         ///< Pointer to free, if NULL, function returns immediately.
+);
+#else
+
+void p_psFree(
+    void *ptr,                        ///< Pointer to free
+    const char *file,                 ///< File of call
+    int lineno                        ///< Line number of call
+);
+
+/// Free memory.  psFree sends file and line number to p_psFree.
+#define psFree(size) p_psFree(size, __FILE__, __LINE__)
+
+#endif
+
+/** Check for memory leaks.  This scans for allocated memory buffers not freed with an ID not less than id0.
+ *  This is used to check for memory leaks by:
+ *      -# before a block of code to be checked, store the current ID count via psGetMemId
+ *      -# after the block of code to be checked, call this function using the ID stored above.  If all
+ *         memory in the block that was allocated has been freed, this call should output nothing and
+ *         return 0.
+ *
+ *  If memory leaks are found, the Memory Problem callback will be called as well.
+ *
+ *  return int  number of memory blocks found as 'leaks', i.e., the number of currently allocated memory
+ *              blocks above id0 that have not been freed.
+ *  @see psAlloc, psFree, psgetMemId, psMemProblemCallbackSet
+ *  @ingroup memTracing
+ */
+int psMemCheckLeaks(
+    psMemoryId id0,                    ///< don't list blocks with id < id0
+    psMemBlock* ** arr,                ///< pointer to array of pointers to leaked blocks, or NULL
+    FILE * fd                          ///< print list of leaks to fd (or NULL)
+);
+
+/** Check for memory corruption.  Scans all currently allocated memory buffers and checks for corruptions,
+ *  i.e., invalid markers that signify a buffer under/overflow.
+ *
+ *  @ingroup memTracing
+ */
+int psMemCheckCorruption(
+    bool abort_on_error                ///< Abort on detecting corruption?
+);
+
+/** Return reference counter
+ *
+ *  @ingroup memRefCount
+ */
+psReferenceCount psMemGetRefCounter(
+    void *vptr                         ///< Pointer to get refCounter for
+);
+
+/** Increment reference counter and return the pointer
+ *
+ *  @ingroup memRefCount
+ */
+#ifdef DOXYGEN
+void *psMemIncrRefCounter(
+    void *vptr                         ///< Pointer to increment refCounter, and return
+);
+#else
+
+void *p_psMemIncrRefCounter(
+    void *vptr,                        ///< Pointer to increment refCounter, and return
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+#define psMemIncrRefCounter(vptr) p_psMemIncrRefCounter(vptr, __FILE__, __LINE__)
+#endif
+
+/** Decrement reference counter and return the pointer
+ *
+ *  @ingroup memRefCount
+ *
+ *  @return void*    the pointer deremented in refCount, or NULL if pointer is 
+ *                   fully dereferenced.
+ */
+#ifdef DOXYGEN
+void* psMemDecrRefCounter(
+    void* vptr                         ///< Pointer to decrement refCounter, and return
+);
+#else
+
+void *p_psMemDecrRefCounter(
+    void *vptr,                        ///< Pointer to decrement refCounter, and return
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+#define psMemDecrRefCounter(vptr) p_psMemDecrRefCounter(vptr, __FILE__, __LINE__)
+#endif
+
+/** Set callback for problems.
+ *
+ *  At various occasions, the memory manager can check the state of the memory 
+ *  stack. If any of these checks discover that the memory stack is corrupted,
+ *  the psMemProblemCallback is called.
+ 
+ *  @ingroup memCallback
+ *
+ *  @return psMemProblemCallback       old psMemProblemCallback function
+ */
+psMemProblemCallback psMemProblemCallbackSet(
+    psMemProblemCallback func          ///< Function to run at memory problem detection
+);
+
+/** Set callback for out-of-memory.
+ *
+ *  If not enough memory is available to satisfy a request by psAlloc or 
+ *  psRealloc, these functions attempt to find an alternative solution by 
+ *  calling the psMemExhaustedCallback, a function which may be set by the 
+ *  programmer in appropriate circumstances, rather than immediately fail. 
+ *  The typical use of such a feature may be when a program needs a large 
+ *  chunk of memory to do an operation, but the exact size is not critical. 
+ *  This feature gives the programmer the opportunity to make a smaller 
+ *  request and try again, limiting the size of the operating buffer.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemExhaustedCallback     old psMemExhaustedCallback function
+ */
+psMemExhaustedCallback psMemExhaustedCallbackSet(
+    psMemExhaustedCallback func        ///< Function to run at memory exhaustion
+);
+
+/** Set call back for when a particular memory block is allocated
+ *
+ *  A private variable, p_psMemAllocateID, can be used to trace the allocation 
+ *  and freeing of specific memory blocks. If p_psMemAllocateID is set and a 
+ *  memory block with that ID is allocated, psMemAllocateCallback is called 
+ *  just before memory is returned to the calling function.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemAllocateCallback      old psMemAllocateCallback function
+ */
+psMemAllocateCallback psMemAllocateCallbackSet(
+    psMemAllocateCallback func       ///< Function to run at memory allocation of specific mem block
+);
+
+/** Set call back for when a particular memory block is freed
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of 
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with 
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemFreeCallback          old psMemFreeCallback function
+ */
+psMemFreeCallback psMemFreeCallbackSet(
+    psMemFreeCallback func             ///< Function to run at memory free of specific mem block
+);
+
+/** get next memory ID
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId                 the next memory ID to be used
+ */
+psMemoryId psMemGetId(void);
+
+/** set p_psMemAllocateID to specific id
+ *
+ *  A private variable, p_psMemAllocateID, can be used to trace the allocation 
+ *  and freeing of specific memory blocks. If p_psMemAllocateID is set and a 
+ *  memory block with that ID is allocated, psMemAllocateCallback is called 
+ *  just before memory is returned to the calling function.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId       
+ *
+ *  @see psMemAllocateCallbackSet    
+ */
+psMemoryId psMemAllocateCallbackSetID(
+    psMemoryId id                      ///< ID to set
+);
+
+/** set p_psMemFreeID to id
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of 
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with 
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId                 the old p_psMemFreeID
+ *
+ *  @see psMemFreeCallbackSet
+ */
+psMemoryId psMemFreeCallbackSetID(
+    psMemoryId id                      ///< ID to set
+);
+
+//@} End of Memory Management Functions
+
+#ifndef DOXYGEN
+
+/*
+ * Ensure that any program using malloc/realloc/free will fail to compile
+ */
+#ifndef PS_ALLOW_MALLOC
+#ifdef __GNUC__
+#pragma GCC poison malloc realloc calloc free
+#else
+#define malloc(S)       _Pragma("error Use of malloc is not allowed.  Use psAlloc instead.")
+#define realloc(P,S)    _Pragma("error Use of realloc is not allowed.  Use psRealloc instead.")
+#define calloc(S)       _Pragma("error Use of calloc is not allowed.  Use psAlloc instead.")
+#define free(P)         _Pragma("error Use of free is not allowed.  Use psFree instead.")
+#endif
+#endif
+
+#endif
+// doxygen skip
+
+#endif // end of header file
Index: /tags/rel2_1/psLib/src/sys/psString.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psString.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psString.c	(revision 1553)
@@ -0,0 +1,103 @@
+
+/** @file  psString.c
+ *
+ *  @brief Contains the definition of string utility functions
+ *
+ *  String utility functions defined shall provide basic string copying
+ *  capabilities while using the preferred memory management utilities.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "psString.h"
+#include "psMemory.h"
+#include "psError.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+char *psStringCopy(const char *str)
+{
+    // Allocate memory using psAlloc function
+    // Copy input string to memory just allocated
+    // Return the copy
+    return strcpy(psAlloc(strlen(str) + 1), str);
+}
+
+char *psStringNCopy(const char *str, int nChar)
+{
+    char *returnValue = NULL;
+
+    // Check the number of characters to copy is non-negative
+    if (nChar < 0) {
+        // Log error message and return NULL
+        psError(__FILE__, "psStringNCopy with negative count specified %d", nChar);
+        return NULL;
+    }
+    // Allocate memory using psAlloc function - nChar bytes
+    // Copy input string to memory allocated up to nChar characters
+    // Return the copy
+    returnValue = strncpy(psAlloc((size_t) nChar + 1), str, (size_t) nChar);
+
+    // Ensure the last byte is NULL character
+    if (nChar > 0) {
+        returnValue[nChar - 1] = '\0';
+    }
+    // Return the string pointer
+    return returnValue;
+}
Index: /tags/rel2_1/psLib/src/sys/psString.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psString.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psString.h	(revision 1553)
@@ -0,0 +1,70 @@
+/** @file  psString.h
+ *
+ *  @brief Contains the declarations of string utility functions
+ *
+ *  @ingroup SysUtils
+ *
+ *  String utility functions defined shall provide basic string copying
+ *  capabilities.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_STRING_H
+#define PS_STRING_H
+
+
+/** This macro will convert the argument to a quoted string */
+#define PS_STRING(S)  #S
+
+// Doxygen group tags
+
+/** @addtogroup SysUtils
+ *  @{
+ */
+
+/** Copies the input string
+ *
+ *  This function shall allocate memory to the length of the input string
+ *  plus one and copy the input string to the newly allocated memory.
+ *
+ *  @return char*      Copy of input string
+ *
+ */
+char *psStringCopy(
+    const char *str
+    /**< Input string of characters to copy */
+);
+
+/** Copies the input string up to the specified number of characters
+ *
+ *  This function shall allocate memory to the length specified by nChar
+ *  plus one and copy the input string to the newly allocated memory.
+ *  This function will only copy nChar bytes from the input to new string,
+ *  so if the input string is larger than nChar characters the copied
+ *  string will be a substring of the input string.  If the input string
+ *  is smaller than nChar bytes then the remaining bytes allocated will
+ *  be set to NULL.
+ *
+ *  @return  char* Copy of input string
+ *
+ */
+
+/*@null@*/
+
+char *psStringNCopy(
+    const char *str,
+    /**< Input string of characters to copy */
+
+    int nChar
+    /**< Number of bytes to allocate for string copy */
+);
+
+/* @} */// Doxygen - End of SystemGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psTrace.c
===================================================================
--- /tags/rel2_1/psLib/src/sys/psTrace.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psTrace.c	(revision 1553)
@@ -0,0 +1,402 @@
+
+/** @file psTrace.c
+ *  \brief basic run-time trace facilities
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the code for procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************
+    NOTES:
+ In the SRD, higher trace levels correspond to a numerically lower trace
+ value in the code.  This is a bit confusing.  For example, a high-level
+ message might be something like "Begin Processing".  The module programmer
+ might give that a numerically low trace level, such as 1, so then any
+ non-zero trace level in that code component will display thatmessage.
+ 
+ We build a tree of trace components.  Every node in the tree has a
+ depth, which is it's distance from the root.  However, this is not
+ not the same thing as a node's "level", which corresponds to the
+ trace level of that node.
+ 
+ I added a function psTraceFree() which frees all nodes in the trace component
+ tree.  Previously, there had been no function in the API which accomplished
+ this purpose.
+ *****************************************************************************/
+
+#ifndef PS_NO_TRACE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "psMemory.h"
+#include "psTrace.h"
+#include "psString.h"
+#include "psError.h"
+
+static p_psComponent* p_psCroot = NULL; // The root of the trace component
+static FILE *p_psTraceFP = NULL;        // File destination for messages.
+
+static void componentFree(p_psComponent* comp);
+static p_psComponent* componentAlloc(const char *name, int level);
+
+/*****************************************************************************
+componentAlloc(): allocate memory for a new node, and initialize members.
+ *****************************************************************************/
+static p_psComponent* componentAlloc(const char *name, int level)
+{
+    p_psComponent* comp = psAlloc(sizeof(p_psComponent));
+
+    p_psMemSetDeallocator(comp, (psFreeFcn) componentFree);
+    comp->name = psStringCopy(name);
+    comp->level = level;
+    comp->n = 0;
+    comp->subcomp = NULL;
+    return comp;
+}
+
+/*****************************************************************************
+componentFree(): free the current node in the root tree, and all children
+nodes as well.
+ *****************************************************************************/
+static void componentFree(p_psComponent* comp)
+{
+    if (comp == NULL) {
+        return;
+    }
+
+    if (comp->subcomp != NULL) {
+        for (int i = 0; i < comp->n; i++) {
+            psFree(comp->subcomp[i]);
+        }
+        psFree(comp->subcomp);
+    }
+
+    psFree((char *)comp->name);
+}
+
+/*****************************************************************************
+initTrace(): simply initialize the component root tree.
+*****************************************************************************/
+static void initTrace(void)
+{
+    if (p_psCroot == NULL) {
+        p_psCroot = componentAlloc(".", PS_DEFAULT_TRACE_LEVEL);
+    }
+}
+
+/*****************************************************************************
+Set all trace levels to zero.
+ *****************************************************************************/
+void p_psTraceReset(p_psComponent* currentNode)
+{
+    int i = 0;
+
+    if (NULL == currentNode) {
+        return;
+    }
+
+    currentNode->level = 0;
+    for (i = 0; i < currentNode->n; i++) {
+        if (NULL == currentNode->subcomp[i]) {
+            psError(__func__,
+                    "Sub-component %d of node %s in the trace tree is NULL.\n", i, currentNode->name);
+        } else {
+            p_psTraceReset(currentNode->subcomp[i]);
+        }
+    }
+    return;
+}
+
+/*****************************************************************************
+Set all trace levels to zero.
+ *****************************************************************************/
+void psTraceReset()
+{
+    p_psTraceReset(p_psCroot);
+}
+
+/*****************************************************************************
+Free all nodes in the component tree.
+ *****************************************************************************/
+void psTraceFree()
+{
+    psFree(p_psCroot);
+}
+
+/*****************************************************************************
+componentAdd(): Adds the component named "addNodeName" to the root tree.
+ 
+NOTE: replace the call to strsep() with a call to strtok(), which conforms
+to ANSI-C.
+ *****************************************************************************/
+static void componentAdd(const char *addNodeName, int level)
+{
+    int i = 0;                  // Loop index variable.
+    char name[strlen(addNodeName) + 1]; // buffer for writeable copy.
+    char *pname = name;
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = p_psCroot;
+    int nodeExists = 0;
+
+    // Is this the root node? If so, simply set level and return.
+    if (strcmp(".", addNodeName) == 0) {
+        p_psCroot->level = level;
+        return;
+    }
+
+    if (addNodeName[0] != '.') {
+        printf("ERROR: failed to add %s to the root component tree.\n", addNodeName);
+        exit(1);
+    }
+
+    strcpy(name, addNodeName);
+    pname = &name[1];
+    // Iterate through the components of addNodeName.  Strip off the first
+    // component of the name, find that in the root tree, or add it if it
+    // does not exist, then move to the next component in the name.
+
+    while (pname != NULL) {
+        firstComponent = strsep(&pname, ".");
+        nodeExists = 0;
+        for (i = 0; i < currentNode->n; i++) {
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                nodeExists = 1;
+                if (pname == NULL) {
+                    currentNode->level = level;
+                }
+            }
+        }
+
+        if (nodeExists == 0) {
+            currentNode->subcomp = psRealloc(currentNode->subcomp,
+                                             (currentNode->n + 1) * sizeof(p_psComponent* ));
+            currentNode->n = (currentNode->n) + 1;
+
+            currentNode->subcomp[(currentNode->n) - 1] = componentAlloc(firstComponent, level);
+        }
+    }
+}
+
+/*****************************************************************************
+    psSetTraceLevel(): add the component named "comp" to the component tree,
+ if it is not already there, and set it's trace level to "level".
+    Input:
+ comp
+ level
+    Output:
+ none
+    Returns:
+ zero
+*****************************************************************************/
+int psTraceSetLevel(const char *comp,   // component of interest
+                    int level)  // desired trace level
+{
+    // If the root component tree does not exist, then initialize it.
+    if (p_psCroot == NULL) {
+        initTrace();
+    }
+    // Add the new component to the component tree.
+    componentAdd(comp, level);
+
+    // return 0 on success.
+    return 0;
+}
+
+/*****************************************************************************
+    doGetTraceLevel()
+ This function recursively searches the root component tree for the
+ component named "name", which is supplied by a parameter.  If it
+ finds that component, it returns the level of that component.
+ Otherwise, it returns ???.
+ 
+    Inputs:
+ name:
+    Outputs:
+ none
+    Returns:
+ The trace level of the "name" component.
+ *****************************************************************************/
+static int doGetTraceLevel(const char *aname)
+{
+    char name[strlen(aname) + 1];       // need a writeable copy: for strsep()
+    char *pname = name;
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = p_psCroot;
+    int i = 0;
+
+    if (NULL == currentNode) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    if (strcmp(".", aname) == 0) {
+        return (p_psCroot->level);
+    }
+
+    if (aname[0] != '.') {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    strcpy(name, aname);
+    pname = &name[1];
+    while (pname != NULL) {
+        firstComponent = strsep(&pname, ".");
+        for (i = 0; i < currentNode->n; i++) {
+            if (NULL == currentNode->subcomp[i]) {
+                psError(__func__,
+                        "Sub-component %d of node %s in trace tree is NULL.\n", i, currentNode->name);
+            }
+
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                if (pname == NULL) {
+                    return (currentNode->level);
+                }
+            }
+        }
+    }
+    return (PS_UNKNOWN_TRACE_LEVEL);
+}
+
+/*****************************************************************************
+    psGetTraceLevel()
+ Return a trace level of "name" in the root component tree.  If the
+ exact string of components in "name" does not exist in the root
+ tree, we return the deepest level of the match.
+    Input:
+ name
+    Output:
+ none
+    Return:
+ The level of "name" in the root component tree.
+ *****************************************************************************/
+int psTraceGetLevel(const char *name)
+{
+    if (p_psCroot == NULL) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+    // Search the component root tree, determine the trace level.
+    return (doGetTraceLevel(name));
+}
+
+/*****************************************************************************
+    doPrintTraceLevels()
+ This function recursively searches the component tree supplied by the
+ parameter "comp" and prints the name and level of each component.
+    Inputs:
+ comp: a node in the component tree.
+ level: the level of that node
+    Outputs:
+ none
+    Returns:
+ null
+ *****************************************************************************/
+static void doPrintTraceLevels(const p_psComponent* comp, int depth)
+{
+    int i = 0;
+
+    if (comp->name[0] == '\0') {
+        printf("%*s%-*s %d\n", depth, "", 20 - depth,
+               "(root)", (comp->level == PS_UNKNOWN_TRACE_LEVEL) ? 0 : comp->level);
+    } else {
+        if (comp->level == PS_UNKNOWN_TRACE_LEVEL) {
+            printf("%*s%-*s %s\n", depth, "", 20 - depth, comp->name, ".");
+        } else {
+            printf("%*s%-*s %d\n", depth, "", 20 - depth, comp->name, comp->level);
+        }
+    }
+
+    for (i = 0; i < comp->n; i++) {
+        doPrintTraceLevels(comp->subcomp[i], depth + 1);
+    }
+}
+
+/*****************************************************************************
+psPrintTraceLevels(): Simply print all the trace levels in the trace level
+component tree.
+Inputs:
+ none
+Outputs:
+ none
+Returns:
+ null
+*****************************************************************************/
+void psTracePrintLevels(void)
+{
+    if (p_psCroot == NULL) {
+        return;
+    }
+
+    doPrintTraceLevels(p_psCroot, 0);
+}
+
+/*****************************************************************************
+p_psTrace(): we display the trace message to standard output if the trace
+level of that message, supplied by the parameter "level" is higher than the
+trace level that is currently associated with the component named by the
+parameter "comp".
+Input:
+ comp
+ level
+ ...  a printf-style output string.
+Output:
+ none
+Return:
+ null
+ *****************************************************************************/
+void p_psTrace(const char *comp,        // component being traced
+               int level,       // desired trace level
+               ...)             // arguments
+{
+    char *fmt = NULL;
+    va_list ap;
+    int i = 0;
+
+    if (NULL == comp) {
+        psError(__func__, "p_psTrace() called on a NULL trace level tree\n");
+    }
+    // Only display this message if it's trace level is less than the level
+    // of it's associatedcomponent.
+    if (level <= psTraceGetLevel(comp)) {
+        va_start(ap, level);
+
+        // The following functions get the variable list of parameters with
+        // which this function was called, and print them to the standard
+        // output.
+        fmt = va_arg(ap, char *);
+
+        if (p_psTraceFP != NULL) {
+            // We indent each message one space for each level of the message.
+            for (i = 0; i < level; i++) {
+                fprintf(p_psTraceFP, " ");
+            }
+            vfprintf(p_psTraceFP, fmt, ap);
+        } else {
+            // We indent each message one space for each level of the message.
+            for (i = 0; i < level; i++) {
+                putchar(' ');
+            }
+            vprintf(fmt, ap);
+        }
+        va_end(ap);
+    }
+    // NOTE: should we free *fmt as well? Read the man page.
+}
+
+void psTraceSetDestination(FILE * fp)
+{
+    p_psTraceFP = fp;
+}
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psTrace.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psTrace.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psTrace.h	(revision 1553)
@@ -0,0 +1,93 @@
+
+/** @file psTrace.h
+ *  \brief basic run-time trace facilities
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_TRACE_H)
+#define PS_TRACE_H 1
+
+#define PS_UNKNOWN_TRACE_LEVEL -9999   // we don't know this name's level
+#define PS_DEFAULT_TRACE_LEVEL 0
+
+/** \addtogroup LogTrace
+ *  \{
+ */
+
+/** Functions **************************************************************/
+
+//#define PS_NO_TRACE 1   ///< to turn off all tracing
+
+#if defined(PS_NO_TRACE)
+#        define psTrace(facil, level, ...) (void)0
+/* do nothing */
+#        define p_psTrace(facil, level, ...)  (void)0
+/* do nothing */
+#        define psTraceSetLevel(facil,level) 0
+#        define psTraceGetLevel(facil) 0
+#        define psTraceReset() (void)0     /* do nothing */
+#        define psTraceFree() (void)0      /* do nothing */
+#        define psTracePrintLevels() (void)0
+/* do nothing */
+#        define psTraceSetDestination(fp) (void)0
+/* do nothing */
+#    else
+
+    /** Basic structure for the component tree.  A component is a string of the
+        form aaa.bbb.ccc, and may itself contain further subcomponents.  The
+        Component structure doesn't in fact contain it's full name, but only the
+        last part. */
+    typedef struct p_psComponent
+    {
+        const char *name;           // last part of name of component
+        int level;                  // trace level for this component
+        int n;                      // number of subcomponents
+        struct p_psComponent* *subcomp;     // next level of subcomponents
+    }
+p_psComponent;
+
+#ifndef DOXYGEN
+/// Send a trace message
+void p_psTrace(const char *facil,       ///< facilty of interest
+               int myLevel,     ///< desired trace level
+               ...)             ///< trace message arguments
+;
+#endif
+
+/// Set trace level
+int psTraceSetLevel(const char *facil,     ///< facilty of interest
+                    int level)     ///< desired trace level
+;
+
+/// Get the trace level
+int psTraceGetLevel(const char *facil)     ///< facilty of interest
+;
+
+/// Set all trace levels to zero (do not free nodes in the component tree).
+void psTraceReset();
+
+/// Free all nodes in the component tree.
+void psTraceFree();
+
+/// print trace levels
+void psTracePrintLevels(void);
+
+/// Set the destination of future trace messages.
+void psTraceSetDestination(FILE * fp);
+
+/* \} */// End of SystemGroup Functions
+
+#define psTrace(facil, level, ...) p_psTrace(facil, level, __VA_ARGS__)
+#endif
+
+#endif
Index: /tags/rel2_1/psLib/src/sys/psType.h
===================================================================
--- /tags/rel2_1/psLib/src/sys/psType.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sys/psType.h	(revision 1553)
@@ -0,0 +1,156 @@
+
+/** @file  psType.h
+*
+*  @brief Contains support for basic types
+*
+*  This file defines common datatypes used throughout psLib.
+*
+*  @ingroup DataContainer
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_TYPE_H
+#define PS_TYPE_H
+
+#include <complex.h>
+#include <stdint.h>
+#include <float.h>
+
+/// @addtogroup DataContainer
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Basic data types used by the containers.
+ *
+ * The basic types of the primitives used by psLib are defined within this enum. This enum is in turn used by
+ * the psType struct.
+ *
+ */
+
+typedef uint8_t psU8;                  ///< 8-bit unsigned int
+typedef uint16_t psU16;                ///< 16-bit unsigned int
+typedef uint32_t psU32;                ///< 32-bit unsigned int
+typedef uint64_t psU64;                ///< 64-bit unsigned int
+typedef int8_t psS8;                   ///< 8-bit signed int
+typedef int16_t psS16;                 ///< 16-bit signed int
+typedef int32_t psS32;                 ///< 32-bit signed int
+typedef int64_t psS64;                 ///< 64-bit signed int
+typedef float psF32;                   ///< 32-bit floating point
+typedef double psF64;                  ///< 64-bit floating point
+typedef complex float psC32;           ///< complex with 32-bit floating point Real and Imagary numbers
+typedef complex double psC64;          ///< complex with 64-bit floating point Real and Imagary numbers
+typedef void *psPTR;                   ///< void pointer
+
+typedef enum {
+    PS_TYPE_S8 = 0x0101,               ///< Character.
+    PS_TYPE_S16 = 0x0102,              ///< Short integer.
+    PS_TYPE_S32 = 0x0104,              ///< Integer.
+    PS_TYPE_S64 = 0x0108,              ///< Long integer.
+    PS_TYPE_U8 = 0x0301,               ///< Unsigned character.
+    PS_TYPE_U16 = 0x0302,              ///< Unsigned short integer.
+    PS_TYPE_U32 = 0x0304,              ///< Unsigned integer.
+    PS_TYPE_U64 = 0x0308,              ///< Unsigned long integer.
+    PS_TYPE_F32 = 0x0404,              ///< Single-precision Floating point.
+    PS_TYPE_F64 = 0x0408,              ///< Double-precision floating point.
+    PS_TYPE_C32 = 0x0808,              ///< Complex numbers consisting of single-precision floating point.
+    PS_TYPE_C64 = 0x0810,              ///< Complex numbers consisting of double-precision floating point.
+    PS_TYPE_PTR = 0x0000               ///< Something else that's not supported for arithmetic.
+} psElemType;
+
+#define PS_TYPE_MASK PS_TYPE_U8        /**< the psElemType to use for mask image */
+#define PS_TYPE_MASK_DATA U8           /**< the data member to use for mask image */
+#define PS_TYPE_MASK_NAME "psU8"       /**< the data type for mask as a string */
+
+typedef psU8 psMaskType;               ///< the C datatype for a mask image
+
+
+#define PS_MIN_S8        INT8_MIN      /**< minimum valid psS8 value */
+#define PS_MIN_S16       INT16_MIN     /**< minimum valid psS16 value */
+#define PS_MIN_S32       INT32_MIN     /**< minimum valid psS32 value */
+#define PS_MIN_S64       INT64_MIN     /**< minimum valid psS64 value */
+#define PS_MIN_U8        0             /**< minimum valid psU8 value */
+#define PS_MIN_U16       0             /**< minimum valid psU16 value */
+#define PS_MIN_U32       0             /**< minimum valid psU32 value */
+#define PS_MIN_U64       0             /**< minimum valid psU64 value */
+#define PS_MIN_F32       -FLT_MAX      /**< minimum valid psF32 value */
+#define PS_MIN_F64       -DBL_MAX      /**< minimum valid psF64 value */
+#define PS_MIN_C32       -FLT_MAX      /**< minimum valid real or imaginary psC32 value */
+#define PS_MIN_C64       -DBL_MAX      /**< minimum valid real or imaginary psC32 value */
+
+#define PS_MAX_S8        INT8_MAX      /**< maximum valid psS8 value */
+#define PS_MAX_S16       INT16_MAX     /**< maximum valid psS16 value */
+#define PS_MAX_S32       INT32_MAX     /**< maximum valid psS32 value */
+#define PS_MAX_S64       INT64_MAX     /**< maximum valid psS64 value */
+#define PS_MAX_U8        UINT8_MAX     /**< maximum valid psU8 value */
+#define PS_MAX_U16       UINT16_MAX    /**< maximum valid psU16 value */
+#define PS_MAX_U32       UINT32_MAX    /**< maximum valid psU32 value */
+#define PS_MAX_U64       UINT64_MAX    /**< maximum valid psU64 value */
+#define PS_MAX_F32       FLT_MAX       /**< maximum valid psF32 value */
+#define PS_MAX_F64       DBL_MAX       /**< maximum valid psF64 value */
+#define PS_MAX_C32       FLT_MAX       /**< maximum valid real or imaginary psC32 value */
+#define PS_MAX_C64       DBL_MAX       /**< maximum valid real or imaginary psC32 value */
+
+/// Macro to get the bad pixel reason code (stored as part of mask value)
+#define PS_BADPIXEL_BITMASK 0x0f
+#define PS_GET_BADPIXEL(maskValue) (maskValue & PS_BADPIXEL_BITMASK)
+
+#define PS_IS_BADPIXEL(maskValue) (PS_GET_BADPIXEL(maskValue) != 0)
+
+/// Macro to apply a bad pixel reason code to mask image
+#define PS_SET_BADPIXEL(maskValue, reasonCode) \
+{ \
+    maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \
+}
+
+/// Macro to determine if the psElemType is an integer.
+#define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100)
+/// Macro to determine if the psElemType is unsigned.
+#define PS_IS_PSELEMTYPE_UNSIGNED(x) ((x & 0x200) == 0x200)
+/// Macro to determine if the psElemType is a real (non-complex) floating-point type.
+#define PS_IS_PSELEMTYPE_REAL(x) ((x & 0x400) == 0x400)
+/// Macro to determine if the psElemType is complex number type.
+#define PS_IS_PSELEMTYPE_COMPLEX(x) ((x & 0x800) == 0x800)
+/// Macro to determine the storage size, in bytes, of the psElemType.
+#define PSELEMTYPE_SIZEOF(x) ( (x==PS_TYPE_PTR) ? sizeof(void*) :(x & 0xFF) )
+
+/** Dimensions of a data type.
+ *
+ * The dimensions of containers used by psLib are defined within this enum. This enum is used by the psType
+struct. *
+ */
+typedef enum {
+    PS_DIMEN_SCALAR,            ///< Scalar.
+    PS_DIMEN_VECTOR,            ///< Vector.
+    PS_DIMEN_TRANSV,            ///< Transposed vector.
+    PS_DIMEN_IMAGE,             ///< Image.
+    PS_DIMEN_OTHER              ///< Something else that's not supported for arithmetic.
+} psDimen;
+
+/** The type of a data type.
+ *
+ * All psLib complex types consist of primitive components. This struct provides the description of those
+ * primitives.
+ *
+ */
+typedef struct
+{
+    psElemType type;            ///< Primitive type.
+    psDimen dimen;              ///< Dimensionality.
+}
+psType;
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/.cvsignore	(revision 1553)
@@ -0,0 +1,1 @@
+*.i
Index: /tags/rel2_1/psLib/src/sysUtils/Makefile
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/Makefile	(revision 1553)
@@ -0,0 +1,82 @@
+###############################################################################
+##
+##  Makefile:   sysUtils
+##
+##  $Revision: 1.18 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-09 20:28:54 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+###############################################################################
+
+# Define variable prefix to the top level project - psLib
+# This is necessary for definition is Makefile.Globals uses prefix
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+# Define the two targets to be built
+
+TARGET_STATIC  = libpslib.a
+
+# Include the make global definitions for the project
+
+include ../Makefile.Globals
+
+# Set CFLAGS used by the implicit rule to compile .c
+
+CFLAGS := $(CFLAGS_RELOC) -I../collections -I../dataManip -I../sysUtils -I../include
+
+# Define the source objects
+ 
+SRC_OBJS = psMemory.o    \
+           psError.o     \
+           psTrace.o     \
+           psLogMsg.o    \
+           psAbort.o     \
+           psString.o    
+
+OBJS = $(addprefix makedir/,$(SRC_OBJS))
+
+# Define PHONY target "all" which will make all the necessary items
+
+all: $(TARGET_STATIC)
+
+# Rule to make static library
+
+libpslib.a: $(OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs ../$@ $(OBJS)
+
+# Define PHONY target "install" which will install necessary files
+
+install: $(TARGET_STATIC) 
+	install *.h $(includedir)
+
+# Define PHONY target "distclean" which will cleanup the distribution
+
+distclean:	clean
+	$(RM) ../$(TARGET_STATIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+
+clean:
+	@echo "    Deleting intermediate files for 'sysUtils'"
+	$(RM) $(OBJS) *.lint
+
+cleandep:
+	$(RM) $(OBJS:.o=.d)
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+makedir/%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+makedir/%.d: %.c
+	$(CC) -MM $(CFLAGS) $< > $@.tmp
+	sed 's|\($*\)\.o[ :]*|\1.o $@ : |g' $@.tmp > $@
+	$(RM) -f $@.tmp
+
+include $(OBJS:.o=.d)
Index: /tags/rel2_1/psLib/src/sysUtils/README
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/README	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/README	(revision 1553)
@@ -0,0 +1,2 @@
+This directory includes code related to the 'system utilities' section of the
+IfA supplied SDR.
Index: /tags/rel2_1/psLib/src/sysUtils/psAbort.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psAbort.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psAbort.c	(revision 1553)
@@ -0,0 +1,89 @@
+
+/** @file  psAbort.c
+ *
+ *  @brief Contains the definition for abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdarg.h>
+#include <stdlib.h>
+#include "psAbort.h"
+#include "psLogMsg.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+void psAbort(const char *name, const char *fmt, ...)
+{
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    // Call logging function with PS_LOG_ABORT level
+    psLogMsgV(name, PS_LOG_ABORT, fmt, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    // Call system abort function to terminate program execution
+    abort();
+}
Index: /tags/rel2_1/psLib/src/sysUtils/psAbort.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psAbort.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psAbort.h	(revision 1553)
@@ -0,0 +1,47 @@
+
+/** @file  psAbort.h
+ *
+ *  @brief Contains the declarations for the abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @ingroup ErrorHandling
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ABORT_H
+#define PS_ABORT_H
+
+// Doxygen grouping tags
+
+/** @addtogroup ErrorHandling
+ *  @{
+ */
+
+/** Reports an abort message to logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of 
+ *  PS_LOG_ABORT and pass the parameters name and fmt to generate a proper
+ *  log message.  After logging, this function will call system abort 
+ *  function to abnormally terminate the program.
+ *
+ *  @return  void No return value
+ *
+ */
+void psAbort(
+    const char *name,                  ///< Source of abort such as file or function detected
+    const char *fmt,                   ///< A printf style formatting statement defining msg
+    ...
+);
+
+/* @} */// Doxygen - End of SystemGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psError.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psError.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psError.c	(revision 1553)
@@ -0,0 +1,86 @@
+
+/** @file  psError.c
+ *
+ *  @brief Contains the definitions for the error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdarg.h>
+#include "psLogMsg.h"
+#include "psError.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATIONS - LOCAL                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATIONS - PUBLIC                                         */
+
+/*****************************************************************************/
+
+void psError(const char *name, const char *fmt, ...)
+{
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    // Call logging function with PS_LOG_ERROR level
+    psLogMsgV(name, PS_LOG_ERROR, fmt, argPtr);
+
+    // Clean up stack after variable argument has been used
+    va_end(argPtr);
+}
Index: /tags/rel2_1/psLib/src/sysUtils/psError.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psError.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psError.h	(revision 1553)
@@ -0,0 +1,43 @@
+
+/** @file  psError.h
+ *
+ *  @brief Contains the declarations for the error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @ingroup ErrorHandling
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ERROR_H
+#define PS_ERROR_H
+
+/** @addtogroup ErrorHandling
+ *  @{
+ */
+
+/** Reports an error message to the logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
+ *  log message.
+ *
+ */
+void psError(
+    const char *name,                  ///< Source of error such as file or function detected
+    const char *fmt,                   ///< A printf style formatting statement defining msg
+    ...
+);
+
+/* @} */// End of SysUtils Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psLogMsg.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psLogMsg.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psLogMsg.c	(revision 1553)
@@ -0,0 +1,365 @@
+
+/** @file  psLogMsg.c
+ *  @brief Procedures for logging messages.
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedure which set
+ *  message log levels, messahe log formats, message log destinations, and
+ *  for generating the messages themselves.
+ *  @ingroup LogTrace
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************
+NOTES: currently, the prototype code has the following global variables:
+    static int p_psGlobalLogDest;
+    static int p_psGlobalLogLevel;
+    static int p_psLogTime;
+    static int p_psLogHost;
+    static int p_psLogLevel;
+    static int p_psLogName;
+    static int p_psLogMsg;
+ *****************************************************************************/
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psTrace.h"
+
+#define MIN_LOG_LEVEL 0
+#define MAX_LOG_LEVEL 9
+
+#define MAX_LOG_LINE_LENGTH 128
+static FILE *logDest = (FILE *) 1;      // flag to initialize to stderr before using.
+static int globalLogLevel = PS_LOG_INFO;        // log all messages at this or above
+static bool logTime = true;     // Flag to include time info
+static bool logHost = true;     // Flag to include host info
+static bool logLevel = true;    // Flag to include level info
+static bool logName = true;     // Flag to include name info
+static bool logMsg = true;      // Flag to include message info
+
+/*****************************************************************************
+psLogSetLevel(): Set the current log level and return old level.
+Input:
+ level (int): the new log level.
+Output:
+ none
+Return:
+ The old log level.
+ *****************************************************************************/
+int psLogSetLevel(int level)
+{
+    // Save old global log level for changing it.
+    int oldLevel = globalLogLevel;
+
+    if ((level < MIN_LOG_LEVEL) || (level > MAX_LOG_LEVEL)) {
+        psLogMsg("logmsg", PS_LOG_WARN, "Attempt to set invalid logMsg level: %d", level);
+        level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
+    }
+    // Set new global log level
+    globalLogLevel = level;
+
+    // Return old global log level
+    return oldLevel;
+}
+
+/*****************************************************************************
+psLogSetDestination(): sets the destination where log messages will be
+sent to.
+ 
+Input:
+ dest (int): the new log destination
+Output:
+ None.
+Return:
+ An integer specifying the old log destination.
+ *****************************************************************************/
+bool psLogSetDestination(const char *dest)
+{
+    char protocol[5];
+    char location[257];
+
+    // if logDest has not been initialized, do so before using it
+    if (logDest == (FILE *) 1) {
+        logDest = stderr;
+    }
+
+    if (dest == NULL || strcmp(dest, "none") == 0) {
+        if (logDest != NULL && logDest != stderr && logDest != stdout) {
+            fclose(logDest);
+        }
+        logDest = NULL;
+        return true;
+    }
+
+    if (sscanf(dest, "%4s:%256s", protocol, location) < 2) {
+        psError(__func__, "The specified destination, %s, is malformed.", dest);
+        return false;
+    }
+
+    if (strcmp(protocol, "dest") == 0) {
+        if (strcmp(location, "stderr") == 0) {
+            if (logDest != NULL && logDest != stderr && logDest != stdout) {
+                fclose(logDest);
+            }
+            logDest = stderr;
+            return true;
+        }
+        if (strcmp(location, "stdout") == 0) {
+            if (logDest != NULL && logDest != stderr && logDest != stdout) {
+                fclose(logDest);
+            }
+            logDest = stdout;
+            return true;
+        }
+        psError(__func__, "The location, %s, for protocol 'dest' is invalid.", location);
+        return 1;
+    } else if (strcmp(protocol, "file") == 0) {
+        FILE *file = fopen(location, "w");
+
+        if (file == NULL) {
+            psError(__func__, "Could not open file '%s' for output.", location);
+            return false;
+        }
+        if (logDest != NULL && logDest != stderr && logDest != stdout) {
+            fclose(logDest);
+        }
+        logDest = file;
+        return true;
+    }
+
+    psError(__func__, "Do not know how to handle the protocol '%s'.", protocol);
+    return false;
+}
+
+/*****************************************************************************
+psLogSetFormat(): Set the format of psLogMsg output.  More precisely,
+    provide a string consisting of the letters {H (host), L (level), M
+    (message), N (name), T (time)}.  The default is "HLMNT".  This string
+    determines whether or not they associated type of information will be
+    included in message logs.  It does not determine the order in which that
+    information will appear (that order is fixed).
+ 
+Input:
+    fmt: a string specifying the format.
+Output:
+    none.
+Return:
+    NULL.
+ *****************************************************************************/
+void psLogSetFormat(const char *fmt)
+{
+    // assume nothing desired unless specified
+    logHost = false;
+    logLevel = false;
+    logMsg = false;
+    logName = false;
+    logTime = false;
+
+    // if fmt is NULL, no logging is desired.
+    if (fmt == NULL) {
+        return;
+    }
+
+    if (strlen(fmt) == 0) {
+        fmt = "THLNM";
+    }
+    // Step through each character in the format string.  For each letter
+    // in that string, set/unset the appropriate logging.
+
+    for (const char *ptr = fmt; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            logHost = true;
+            break;
+        case 'L':
+        case 'l':
+            logLevel = true;
+            break;
+        case 'M':
+        case 'm':
+            logMsg = true;
+            break;
+        case 'N':
+        case 'n':
+            logName = true;
+            break;
+        case 'T':
+        case 't':
+            logTime = true;
+            break;
+        default:
+            psError(__func__, "Unknown logging keyword %c", *ptr);
+            break;
+        }
+    }
+
+    if (!logMsg) {
+        psTrace("utils.logMsg", 1, "You must at least log error messages (You chose \"%s\")", fmt);
+    }
+}
+
+#if !defined(HOST_NAME_MAX)                // should be in limits.h
+#define HOST_NAME_MAX 256
+#endif
+
+/*****************************************************************************
+    psVLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name
+ level
+ fmt
+ ap
+    Output:
+ none
+    Return:
+ NULL.
+ *****************************************************************************/
+void psLogMsgV(const char *name, int level, const char *fmt, va_list ap)
+{
+    static int first = 1;       // Flag for calling gethostname()
+    static char hostname[HOST_NAME_MAX + 1];
+
+    // Buffer for hostname.
+    char clevel = 0;            // letter-name for level
+    char head[MAX_LOG_LINE_LENGTH + 2]; // the added two are for the ending | and \0
+    char *head_ptr = head;      // where we've got to in head
+    int maxLength = MAX_LOG_LINE_LENGTH;
+    time_t clock = time(NULL);  // The current time.
+    struct tm *utc = gmtime(&clock);    // The current gm time.
+
+    // if logDest has not been initialized, do so before using it
+    if (logDest == (FILE *) 1) {
+        logDest = stderr;
+    }
+    // If logging is off, or if the level is too high, return immediately.
+    if ((level > globalLogLevel) || (logDest == NULL)) {
+        return;
+    }
+    // If I have not been here yet, determine my hostname and save it.
+    if (first) {
+        first = 0;
+        gethostname(hostname, HOST_NAME_MAX);
+    }
+
+    switch (level) {
+    case PS_LOG_ABORT:
+        clevel = 'A';
+        break;
+
+    case PS_LOG_ERROR:
+        clevel = 'E';
+        break;
+
+    case PS_LOG_WARN:
+        clevel = 'W';
+        break;
+
+    case PS_LOG_INFO:
+        clevel = 'I';
+        break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        clevel = level + '0';
+        break;
+
+    default:
+        psTrace("utils.logMsg", 2, "Invalid logMsg level: %d (%s)\n", level, fmt);
+        level = (level < 0) ? 0 : 9;
+        break;
+    }
+
+    // Create the various log fields...
+    if (logTime) {
+        maxLength -= snprintf(head_ptr, maxLength, "%4d:%02d:%02d %02d:%02d:%02dZ",
+                              utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                              utc->tm_hour, utc->tm_min, utc->tm_sec) - 1;
+        head_ptr += strlen(head_ptr);
+    }
+    // Hostname should be 20 characters.
+    if (logHost) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%-20s", hostname);
+        head_ptr += strlen(head_ptr);
+    }
+    if (logLevel) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%c", clevel);
+        head_ptr += strlen(head_ptr);
+    }
+    // The name field must be 15 characters.
+    if (logName) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%15.15s", name);
+        head_ptr += strlen(head_ptr);
+    }
+
+    if (head_ptr > head) {
+        *head_ptr++ = '|';
+    } else if (!logMsg) {                  // no output desired
+        return;
+    }
+    *head_ptr = '\0';
+
+    fputs(head, logDest);
+    if (logMsg) {
+        vfprintf(logDest, fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            fputc('\n', logDest);
+        }
+    } else {
+        fputc('\n', logDest);
+    }
+}
+
+/*****************************************************************************
+    psLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name: Indicates the source of this log message.
+ level: The severity of this log message.
+ fmt: The printf-stype formatted string, followed by the arguments
+  to that string.
+ ... The arguments to the above printf-style string.
+    Output:
+ none
+    Return:
+ NULL
+ *****************************************************************************/
+void psLogMsg(const char *name, int level, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    psLogMsgV(name, level, fmt, ap);
+    va_end(ap);
+}
Index: /tags/rel2_1/psLib/src/sysUtils/psLogMsg.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psLogMsg.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psLogMsg.h	(revision 1553)
@@ -0,0 +1,104 @@
+
+/** @file  psLogMsg.h
+ *  @brief Procedures for logging messages.
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedure which set
+ *  message log levels, messahe log formats, message log destinations, and
+ *  for generating the messages themselves.
+ *  @ingroup LogTrace
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_LOG_MSG_H)
+#define PS_LOG_MSG_H
+#include <stdarg.h>
+#include <stdbool.h>
+
+/** @addtogroup LogTrace
+ *  @{
+ */
+
+/** This procedure sets the destination for future log messages.  Currently
+ *  the destination is specified by an integer which can have the following
+ *  pre-defined values: PS_LOG_NONE, PS_LOG_TO_STDOUT, and PS_LOG_TO_STDERR.
+ *  In future versions, this procedure will take a character string as an
+ *  argument which can specify more general log destinations.
+ *
+ *  @return int     true if set successfully, otherwise false.
+ */
+bool psLogSetDestination(
+    const char *dest                   ///< Specifies where to send messages.
+);
+
+/** This procedure sets the message level for future log messages.  Subsequent
+ *  log messages, with a log level of "mylevel", will only be logged if
+ *  "mylevel" is less than the current log level set by this procedure.
+ *  Ie. higher values set by this procedure will cause more log messages to
+ *  be displayed.
+ *
+ *  @return int    old logging level
+ */
+int psLogSetLevel(
+    int level                          ///< Specifies the system log level
+);
+
+/** This procedure sets the log format for future log messages.  The argument
+ *  must be a character string consistsing of the letters H (host), L
+ *  (level), M (message), N (name), and T (time).  The default is "THLNM".
+ *  Deleting a letter from the string will cause the associated information
+ *  to not be logged.
+ *
+ */
+void psLogSetFormat(
+    const char *fmt                    ///< Specifies the system log format
+);
+
+/** This procedure logs a message to the destination set by a prior
+ *  call to psLogSetDestination(), if myLevel is less than the level
+ *  specified by a prior call to psLogSetLevel().  The message is specified
+ *  with a printf-stype string an arguments.
+ *
+ */
+void psLogMsg(
+    const char *name,                  ///< name of the log source
+    int myLevel,                       ///< severity level of this log message
+    const char *fmt,                   ///< printf-style format command
+    ...
+);
+
+/** This procedure is functionally equivalent to psLogMsg(), except that
+ *  it takes a va_list as the message parameter, not a printf-style string.
+ *
+ */
+void psLogMsgV(
+    const char *name,                  ///< name of the log source
+    int myLevel,                       ///< severity level of this log message
+    const char *fmt,                   ///< printf-style format command
+    va_list ap                         ///< varargs argument list
+);
+
+///< Status codes for log messages
+enum {
+    PS_LOG_ABORT = 0,                  ///< log message is a critical error, perform an abort after printing
+    PS_LOG_ERROR,                      ///< log message is an error, but don't abort
+    PS_LOG_WARN,                       ///< log message is a warning
+    PS_LOG_INFO                        ///< log message is informational only
+};
+
+///< Destinations for log messages
+enum {
+    PS_LOG_NONE,                       ///< turn off logging
+    PS_LOG_TO_STDERR,                  ///< log to system's stderr
+    PS_LOG_TO_STDOUT                   ///< log to system's stdout
+};
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psMemory.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psMemory.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psMemory.c	(revision 1553)
@@ -0,0 +1,631 @@
+
+/** @file  psMemory.c
+*
+*  @brief Contains the definitions for the memory management system
+*
+*  psMemory.h has additional information and documentation of the routines found in this file.
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Robert Lupton, Princeton University
+*
+*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:58 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#define PS_ALLOW_MALLOC                    // we're allowed to call malloc()
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psLogMsg.h"
+
+#define P_PS_MEMMAGIC (void *)0xdeadbeef   // Magic number in psMemBlock header
+
+#define P_PS_LARGE_BLOCK_SIZE 65536        // size where under, we try to recycle
+
+static int checkMemBlock(const psMemBlock* m, const char *funcName);
+static psMemBlock* lastMemBlockAllocated = NULL;
+static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int recycleBins = 13;
+static int recycleBinSize[14] = {
+                                    8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE
+                                };
+
+// N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops)
+static psMemBlock* recycleMemBlockList[13] = {
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+        };
+
+#ifdef PS_MEM_DEBUG
+static psMemBlock* deadBlockList;       // a place to put dead memBlocks in debug mode.
+#endif
+
+/**
+ * Unique ID for allocated blocks
+ */
+static psMemoryId memid = 0;
+
+/**
+ *  Default memExhausted callback.
+ */
+static void *memExhaustedCallbackDefault(size_t size)
+{
+    void *ptr = NULL;
+
+    pthread_mutex_lock(&recycleMemBlockListMutex);
+    int level = recycleBins - 1;
+
+    while (level >= 0 && ptr == NULL) {
+        while (recycleMemBlockList[level] != NULL && ptr == NULL) {
+            psMemBlock* old = recycleMemBlockList[level];
+
+            recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;
+            free(old);
+            ptr = malloc(size);
+        }
+        level--;
+    }
+    pthread_mutex_unlock(&recycleMemBlockListMutex);
+
+    return ptr;
+}
+
+static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault;
+
+psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func)
+{
+    psMemExhaustedCallback old = memExhaustedCallback;
+
+    if (func != NULL) {
+        memExhaustedCallback = func;
+    } else {
+        memExhaustedCallback = memExhaustedCallbackDefault;
+    }
+
+    return old;
+}
+
+static void memProblemCallbackDefault(const psMemBlock* ptr, const char *file, int lineno)
+{
+    if (ptr->refCounter < 1) {
+        psError(__func__,
+                "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
+                ptr->id, ptr->file, ptr->lineno, file, lineno);
+    }
+
+    if (lineno > 0) {
+        psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);
+    }
+}
+static psMemProblemCallback memProblemCallback = memProblemCallbackDefault;
+
+psMemProblemCallback psMemProblemCallbackSet(psMemProblemCallback func)
+{
+    psMemProblemCallback old = memProblemCallback;
+
+    if (func != NULL) {
+        memProblemCallback = func;
+    } else {
+        memProblemCallback = memProblemCallbackDefault;
+    }
+
+    return old;
+}
+
+/*
+ * And now the I-want-to-be-informed callbacks
+ *
+ * Call the callbacks when these IDs are allocated/freed
+ */
+psMemoryId p_psMemAllocateID = 0;       // notify user this block is allocated
+psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
+
+psMemoryId psMemAllocateCallbackSetID(psMemoryId id)
+{
+    psMemoryId old = p_psMemAllocateID;
+
+    p_psMemAllocateID = id;
+
+    return old;
+}
+
+psMemoryId psMemFreeCallbackSetID(psMemoryId id)
+{
+    psMemoryId old = p_psMemFreeID;
+
+    p_psMemFreeID = id;
+
+    return old;
+}
+
+/*
+ * Default callback for both allocate and free. Note that the
+ * value of p_psMemAllocateID/p_psMemFreeID is incremented
+ * by the return value (so returning 0 means that the callback
+ * isn't resignalled)
+ */
+static psMemoryId memAllocateCallbackDefault(const psMemBlock* ptr)
+{
+    static psMemoryId incr = 0; // "p_psMemAllocateID += incr"
+
+    return incr;
+}
+
+static psMemoryId memFreeCallbackDefault(const psMemBlock* ptr)
+{
+    static psMemoryId incr = 0; // "p_psMemFreeID += incr"
+
+    return incr;
+}
+
+/*
+ * The default callbacks, and the routines to change them
+ */
+static psMemAllocateCallback memAllocateCallback = memAllocateCallbackDefault;
+static psMemFreeCallback memFreeCallback = memFreeCallbackDefault;
+
+psMemAllocateCallback psMemAllocateCallbackSet(psMemAllocateCallback func)
+{
+    psMemFreeCallback old = memAllocateCallback;
+
+    if (func != NULL) {
+        memAllocateCallback = func;
+    } else {
+        memAllocateCallback = memAllocateCallbackDefault;
+    }
+
+    return old;
+}
+
+psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func)
+{
+    psMemFreeCallback old = memFreeCallback;
+
+    if (func != NULL) {
+        memFreeCallback = func;
+    } else {
+        memFreeCallback = memFreeCallbackDefault;
+    }
+
+    return old;
+}
+
+/*
+ * Return memory ID counter for next block to be allocated
+ */
+psMemoryId psMemGetId(void)
+{
+    psMemoryId id;
+
+    pthread_mutex_lock(&memIdMutex);
+    id = memid + 1;
+    pthread_mutex_unlock(&memIdMutex);
+
+    return id;
+}
+
+/*
+ * Routines to check the consistency of the allocated and/or free memory arena
+ *
+ * N.b. If the block wasn't allocated by psAlloc, it will appear corrupted
+ */
+
+static int checkMemBlock(const psMemBlock* m, const char *funcName)
+{
+    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
+    // we shouldn't call such things as p_psAlloc/p_psFree here.
+
+    if (m == NULL) {
+        psError(funcName, "Memory Corruption: NULL memory block found.");
+        return 1;
+    }
+
+    if (m->refCounter == 0) {
+        // using an unreferenced block of memory, are you?
+        psError(__func__, "Memory Corruption: memory block %ld was freed but still used.", m->id);
+        return 1;
+    }
+
+    if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
+        psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)", m->id);
+        return 1;
+    }
+    if (*(void **)((int8_t *) (m + 1) + m->userMemorySize) != P_PS_MEMMAGIC) {
+        psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", m->id);
+        return 1;
+    }
+
+    return 0;
+}
+
+int psMemCheckCorruption(bool abort_on_error)
+{
+    int nbad = 0;               // number of bad blocks
+
+    // get exclusive access to the memBlock list to avoid it changing on us while we use it.
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock) {
+        if (checkMemBlock(iter, __func__)) {
+            nbad++;
+
+            memProblemCallback(iter, __func__, __LINE__);
+
+            if (abort_on_error) {
+                // release the lock on the memblock list
+                pthread_mutex_unlock(&memBlockListMutex);
+                psAbort(__func__, "Detected memory corruption");
+                return nbad;
+            }
+        }
+    }
+
+    // release the lock on the memblock list
+    pthread_mutex_unlock(&memBlockListMutex);
+    return nbad;
+}
+
+void *p_psAlloc(size_t size, const char *file, int lineno)
+{
+
+    psMemBlock* ptr = NULL;
+
+    // memory is of the size I want to bother recycling?
+    if (size < P_PS_LARGE_BLOCK_SIZE) {
+        // find the bin we need.
+        int level = 0;
+
+        while (size > recycleBinSize[level]) {
+            level++;
+        }
+        // Are we in one of the bins
+        if (level < recycleBins) {
+
+            size = recycleBinSize[level];  // round-up size to next sized bin.
+
+            pthread_mutex_lock(&recycleMemBlockListMutex);
+
+            if (recycleMemBlockList[level] != NULL) {
+                ptr = recycleMemBlockList[level];
+                recycleMemBlockList[level] = ptr->nextBlock;
+                if (recycleMemBlockList[level] != NULL) {
+                    recycleMemBlockList[level]->previousBlock = NULL;
+                }
+                size = ptr->userMemorySize;
+            }
+
+            pthread_mutex_unlock(&recycleMemBlockListMutex);
+        }
+    }
+
+    if (ptr == NULL) {
+        ptr = malloc(sizeof(psMemBlock) + size + sizeof(void *));
+
+        if (ptr == NULL) {
+            ptr = memExhaustedCallback(size);
+            if (ptr == NULL) {
+                psAbort(__func__, "Failed to allocate %u bytes at %s:%d", size, file, lineno);
+            }
+        }
+
+        ptr->startblock = P_PS_MEMMAGIC;
+        ptr->endblock = P_PS_MEMMAGIC;
+        ptr->userMemorySize = size;
+        pthread_mutex_init(&ptr->refCounterMutex, NULL);
+    }
+    // increment the memory id safely.
+    pthread_mutex_lock(&memBlockListMutex);
+    *(psMemoryId* ) & ptr->id = ++memid;
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    ptr->file = file;
+    ptr->freeFcn = NULL;
+    *(unsigned int *)&ptr->lineno = lineno;
+    *(void **)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
+    ptr->previousBlock = NULL;
+
+    ptr->refCounter = 1;                   // one user so far
+
+    // need exclusive access of the memory block list now...
+    pthread_mutex_lock(&memBlockListMutex);
+
+    // insert the new block to the front of the memBlock linked-list
+    ptr->nextBlock = lastMemBlockAllocated;
+    if (ptr->nextBlock != NULL) {
+        ptr->nextBlock->previousBlock = ptr;
+    }
+    lastMemBlockAllocated = ptr;
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    // Did the user ask to be informed about this allocation?
+    if (ptr->id == p_psMemAllocateID) {
+        p_psMemAllocateID += memAllocateCallback(ptr);
+    }
+    // And return the user the memory that they allocated
+    return ptr + 1;                        // user memory
+}
+
+void *p_psRealloc(void *vptr, size_t size, const char *file, int lineno)
+{
+    if (vptr == NULL) {
+        return p_psAlloc(size, file, lineno);
+    } else {
+        psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+        bool isBlockLast = false;
+
+        if (checkMemBlock(ptr, __func__) != 0) {
+            memProblemCallback(ptr, file, lineno);
+            psAbort(file, "Realloc detected a memory corruption (id %ld @ %s:%d).",
+                    ptr->id, ptr->file, ptr->lineno);
+        }
+
+        pthread_mutex_lock(&memBlockListMutex);
+
+        isBlockLast = (ptr == lastMemBlockAllocated);
+
+        ptr = (psMemBlock* ) realloc(ptr, sizeof(psMemBlock) + size + sizeof(void *));
+
+        if (ptr == NULL) {
+            psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d", size, file, lineno);
+        }
+
+        ptr->userMemorySize = size;
+        *(void **)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
+
+        if (isBlockLast) {
+            lastMemBlockAllocated = ptr;
+        }
+        // the block location may have changed, so fix the linked list addresses.
+        if (ptr->nextBlock != NULL) {
+            ptr->nextBlock->previousBlock = ptr;
+        }
+        if (ptr->previousBlock != NULL) {
+            ptr->previousBlock->nextBlock = ptr;
+        }
+
+        pthread_mutex_unlock(&memBlockListMutex);
+
+        // Did the user ask to be informed about this allocation?
+        if (ptr->id == p_psMemAllocateID) {
+            p_psMemAllocateID += memAllocateCallback(ptr);
+        }
+
+        return ptr + 1;                    // usr memory
+    }
+}
+
+void p_psFree(void *vptr, const char *file, int lineno)
+{
+    (void)p_psMemDecrRefCounter(vptr, file, lineno);    // this handles the free, if required.
+}
+
+/*
+ * Check for memory leaks.
+ */
+int psMemCheckLeaks(psMemoryId id0, psMemBlock* ** arr, FILE * fd)
+{
+    int nleak = 0;
+    int j = 0;
+    psMemBlock* topBlock = lastMemBlockAllocated;
+
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
+        if ((psMemGetRefCounter(iter + 1) > 0) && (iter->id >= id0)) {
+            nleak++;
+
+            if (fd != NULL) {
+                if (nleak == 1) {
+                    fprintf(fd, "   %20s:line ID\n", "file");
+                }
+
+                fprintf(fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);
+            }
+        }
+    }
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    if (nleak == 0 || arr == NULL) {
+        return nleak;
+    }
+
+    *arr = p_psAlloc(nleak * sizeof(psMemBlock), __FILE__, __LINE__);
+    pthread_mutex_lock(&memBlockListMutex);
+
+    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
+        if ((psMemGetRefCounter(iter + 1) > 0) && (iter->id >= id0)) {
+            (*arr)[j++] = iter;
+            if (j == nleak) {              // found them all
+                break;
+            }
+        }
+    }
+
+    pthread_mutex_unlock(&memBlockListMutex);
+
+    return nleak;
+}
+
+/*
+ * Reference counting APIs
+ */
+// return refCounter
+psReferenceCount psMemGetRefCounter(void *vptr)
+{
+    psMemBlock* ptr;
+    unsigned int refCount;
+
+    if (vptr == NULL) {
+        return 0;
+    }
+
+    ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+    refCount = ptr->refCounter;
+    pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    return refCount;
+}
+
+// increment and return refCounter
+void *p_psMemIncrRefCounter(void *vptr, const char *file, int lineno)
+{
+    psMemBlock* ptr;
+
+    if (vptr == NULL) {
+        return vptr;
+    }
+
+    ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__)) {
+        memProblemCallback(ptr, file, lineno);
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+    ptr->refCounter++;
+    pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    return vptr;
+}
+
+// decrement and return refCounter
+void *p_psMemDecrRefCounter(void *vptr, const char *file, int lineno)
+{
+    if (vptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, file, lineno);
+        return NULL;
+    }
+
+    pthread_mutex_lock(&ptr->refCounterMutex);
+
+    if (ptr->refCounter > 1) {
+        // / XXX - Probably should have another mutex here.
+        ptr->refCounter--;                 // multiple references, just decrement the count.
+        pthread_mutex_unlock(&ptr->refCounterMutex);
+
+    } else {
+        pthread_mutex_unlock(&ptr->refCounterMutex);
+
+        // Did the user ask to be informed about this deallocation?
+        if (ptr->id == p_psMemFreeID) {
+            p_psMemFreeID += memFreeCallback(ptr);
+        }
+
+        if (ptr->freeFcn != NULL) {
+            ptr->freeFcn(vptr);
+        }
+
+        pthread_mutex_lock(&memBlockListMutex);
+
+        // cut the memBlock out of the memBlock list
+        if (ptr->nextBlock != NULL) {
+            ptr->nextBlock->previousBlock = ptr->previousBlock;
+        }
+        if (ptr->previousBlock != NULL) {
+            ptr->previousBlock->nextBlock = ptr->nextBlock;
+        }
+        if (lastMemBlockAllocated == ptr) {
+            lastMemBlockAllocated = ptr->nextBlock;
+        }
+
+        pthread_mutex_unlock(&memBlockListMutex);
+
+        // do we need to recycle?
+        if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) {
+
+            int level = 1;
+
+            while (ptr->userMemorySize >= recycleBinSize[level]) {
+                level++;
+            }
+            level--;
+
+            ptr->refCounter = 0;
+            ptr->previousBlock = NULL;
+
+            pthread_mutex_lock(&recycleMemBlockListMutex);
+            ptr->nextBlock = recycleMemBlockList[level];
+            if (recycleMemBlockList[level] != NULL) {
+                recycleMemBlockList[level]->previousBlock = ptr;
+            }
+            recycleMemBlockList[level] = ptr;
+            pthread_mutex_unlock(&recycleMemBlockListMutex);
+
+        } else {
+            // memory is larger than I want to recycle.
+            #ifdef PS_MEM_DEBUG
+            (void)p_psRealloc(vptr, 0, file, lineno);
+            ptr->previousBlock = NULL;
+            ptr->nextBlock = deadBlockList;
+            if (deadBlockList != NULL) {
+                deadBlockList->previous = ptr;
+            }
+            deadBlockList = ptr;
+            #else
+
+            pthread_mutex_destroy(&ptr->refCounterMutex);
+            free(ptr);
+            #endif
+
+        }
+
+        vptr = NULL;                       // since we freed it, make sure we return NULL.
+    }
+
+    return vptr;
+}
+
+void p_psMemSetDeallocator(void *vptr, psFreeFcn freeFcn)
+{
+    if (vptr == NULL) {
+        return;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    ptr->freeFcn = freeFcn;
+
+}
+psFreeFcn p_psMemGetDeallocator(void *vptr)
+{
+    if (vptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (checkMemBlock(ptr, __func__) != 0) {
+        memProblemCallback(ptr, __func__, __LINE__);
+    }
+
+    return ptr->freeFcn;
+}
Index: /tags/rel2_1/psLib/src/sysUtils/psMemory.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psMemory.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psMemory.h	(revision 1553)
@@ -0,0 +1,393 @@
+/** @file  psMemory.h
+ *
+ *  @brief Contains the definitions for the memory management system
+ *
+ *  This is the generic memory management system put inbetween the user's high level code and the OS-level
+ *  memory allocation routines.  This system adds such features as callback routines for memory error events,
+ *  tracing capabilities, and reference counting.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Robert Lupton, Princeton University
+ *
+ *  @ingroup MemoryManagement
+ *
+ *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#if !defined(PS_MEMORY_H)
+#define PS_MEMORY_H
+
+#include <stdio.h>                     // needed for FILE
+#include <stdbool.h>
+#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
+
+/** @addtogroup MemoryManagement
+ *  @{
+ */
+
+/**
+ *  @addtogroup memCallback Memory Callbacks
+ *
+ *  Routines dealing with the creating and setting of memory management callback functions.
+ */
+
+/**
+ *  @addtogroup memTracing Memory Tracing
+ *
+ *  Routines dealing with memory tracing and corruption checking.
+ */
+
+/**
+ *  @addtogroup memRefCount Reference Count
+ *
+ *  Routines dealing with the reference counting of allocated buffers.
+ */
+
+/// typedef for memory identification numbers.  Guaranteed to be some variety of integer.
+typedef unsigned long psMemoryId;
+
+/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
+typedef unsigned long psReferenceCount;
+
+/// typedef for deallocator.
+typedef void (*psFreeFcn) (void *ptr);
+
+/** Book-keeping data for storage allocator.
+ *  N.b. sizeof(psMemBlock) must be chosen such that if ptr is a pointer
+ *  returned by malloc, then ((char *)ptr + sizeof(psMemBlock)) is properly
+ *  aligned for all storage types.
+ */
+typedef struct psMemBlock
+{
+    const void *startblock;            ///< initialised to p_psMEMMAGIC
+    struct psMemBlock* previousBlock;  ///< previous block in allocation list
+    struct psMemBlock* nextBlock;      ///< next block allocation list
+    psFreeFcn freeFcn;                 ///< deallocator.  If NULL, use generic deallocation.
+    size_t userMemorySize;             ///< the size of the user-portion of the memory block
+    const psMemoryId id;               ///< a unique ID for this allocation
+    const char *file;                  ///< set from __FILE__ in e.g. p_psAlloc
+    const int lineno;                  ///< set from __LINE__ in e.g. p_psAlloc
+    pthread_mutex_t refCounterMutex;   ///< mutex to ensure exclusive access to reference counter
+    psReferenceCount refCounter;       ///< how many times pointer is referenced
+    const void *endblock;              ///< initialised to p_psMEMMAGIC
+}
+psMemBlock;
+
+/** prototype of a basic callback used by memory functions
+ *
+ *  @see psMemAllocateCallbackSet
+ *  @ingroup memCallback
+ */
+typedef psMemoryId(*psMemAllocateCallback) (
+    const psMemBlock* ptr              ///< the psMemBlock just allocated
+);
+
+/** prototype of memory free callback used by memory functions
+ *
+ *  @see psMemFreeCallbackSet
+ *  @ingroup memCallback
+ */
+typedef psMemoryId(*psMemFreeCallback) (
+    const psMemBlock* ptr              ///< the psMemBlock being freed
+);
+
+/** prototype of a callback used in error conditions
+ *
+ *  This callback should not try to call psAlloc or psFree.
+ *
+ *  @see psMemProblemCallbackSet
+ *  @ingroup memCallback
+ */
+typedef void (*psMemProblemCallback) (
+    const psMemBlock* ptr,             ///< the pointer to the problematic memory block.
+    const char *file,                  ///< the file in which the problem originated
+    int lineno                         ///< the line number in which the problem originated
+);
+
+/** prototype of a callback function used when memory runs out
+ *
+ *  @return void* pointer to requested buffer of the size size_t, or NULL if memory could not
+ *          be found.
+ *
+ *  @see psMemExhaustedCallbackSet
+ *  @ingroup memCallback
+ */
+typedef void *(*psMemExhaustedCallback) (
+    size_t size                        ///< the size of buffer required
+);
+
+/** Memory allocation.  This operates much like malloc(), but is guaranteed to return a non-NULL value.
+ *
+ *  @return void* pointer to the allocated buffer. This will not be NULL.
+ *  @see psFree 
+ */
+#ifdef DOXYGEN
+void *psAlloc(size_t size       ///< Size required
+             );
+#else
+
+void *p_psAlloc(size_t size,    ///< Size required
+                const char *file,       ///< File of call
+                int lineno      ///< Line number of call
+               );
+
+void p_psMemSetDeallocator(void *ptr, psFreeFcn freeFcn);
+psFreeFcn p_psMemGetDeallocator(void *ptr);
+
+/// Memory allocation. psAlloc sends file and line number to p_psAlloc.
+#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
+#endif
+
+/** Memory re-allocation.  This operates much like realloc(), but is guaranteed to return a non-NULL value.
+ *
+ *  @return void* pointer to resized buffer. This will not be NULL.
+ *  @see psAlloc, psFree
+ */
+#ifdef DOXYGEN
+void *psRealloc(
+    void *ptr                          ///< Pointer to re-allocate
+    size_t size,                       ///< Size required
+);
+#else
+
+void *p_psRealloc(
+    void *ptr,                         ///< Pointer to re-allocate
+    size_t size,                       ///< Size required
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+/// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
+#define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
+
+#endif
+
+/** Free memory.  This operates much like free().
+ *
+ *  @see psAlloc, psRealloc
+ */
+#ifdef DOXYGEN
+void psFree(
+    void *ptr,                         ///< Pointer to free, if NULL, function returns immediately.
+);
+#else
+
+void p_psFree(
+    void *ptr,                        ///< Pointer to free
+    const char *file,                 ///< File of call
+    int lineno                        ///< Line number of call
+);
+
+/// Free memory.  psFree sends file and line number to p_psFree.
+#define psFree(size) p_psFree(size, __FILE__, __LINE__)
+
+#endif
+
+/** Check for memory leaks.  This scans for allocated memory buffers not freed with an ID not less than id0.
+ *  This is used to check for memory leaks by:
+ *      -# before a block of code to be checked, store the current ID count via psGetMemId
+ *      -# after the block of code to be checked, call this function using the ID stored above.  If all
+ *         memory in the block that was allocated has been freed, this call should output nothing and
+ *         return 0.
+ *
+ *  If memory leaks are found, the Memory Problem callback will be called as well.
+ *
+ *  return int  number of memory blocks found as 'leaks', i.e., the number of currently allocated memory
+ *              blocks above id0 that have not been freed.
+ *  @see psAlloc, psFree, psgetMemId, psMemProblemCallbackSet
+ *  @ingroup memTracing
+ */
+int psMemCheckLeaks(
+    psMemoryId id0,                    ///< don't list blocks with id < id0
+    psMemBlock* ** arr,                ///< pointer to array of pointers to leaked blocks, or NULL
+    FILE * fd                          ///< print list of leaks to fd (or NULL)
+);
+
+/** Check for memory corruption.  Scans all currently allocated memory buffers and checks for corruptions,
+ *  i.e., invalid markers that signify a buffer under/overflow.
+ *
+ *  @ingroup memTracing
+ */
+int psMemCheckCorruption(
+    bool abort_on_error                ///< Abort on detecting corruption?
+);
+
+/** Return reference counter
+ *
+ *  @ingroup memRefCount
+ */
+psReferenceCount psMemGetRefCounter(
+    void *vptr                         ///< Pointer to get refCounter for
+);
+
+/** Increment reference counter and return the pointer
+ *
+ *  @ingroup memRefCount
+ */
+#ifdef DOXYGEN
+void *psMemIncrRefCounter(
+    void *vptr                         ///< Pointer to increment refCounter, and return
+);
+#else
+
+void *p_psMemIncrRefCounter(
+    void *vptr,                        ///< Pointer to increment refCounter, and return
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+#define psMemIncrRefCounter(vptr) p_psMemIncrRefCounter(vptr, __FILE__, __LINE__)
+#endif
+
+/** Decrement reference counter and return the pointer
+ *
+ *  @ingroup memRefCount
+ *
+ *  @return void*    the pointer deremented in refCount, or NULL if pointer is 
+ *                   fully dereferenced.
+ */
+#ifdef DOXYGEN
+void* psMemDecrRefCounter(
+    void* vptr                         ///< Pointer to decrement refCounter, and return
+);
+#else
+
+void *p_psMemDecrRefCounter(
+    void *vptr,                        ///< Pointer to decrement refCounter, and return
+    const char *file,                  ///< File of call
+    int lineno                         ///< Line number of call
+);
+
+#define psMemDecrRefCounter(vptr) p_psMemDecrRefCounter(vptr, __FILE__, __LINE__)
+#endif
+
+/** Set callback for problems.
+ *
+ *  At various occasions, the memory manager can check the state of the memory 
+ *  stack. If any of these checks discover that the memory stack is corrupted,
+ *  the psMemProblemCallback is called.
+ 
+ *  @ingroup memCallback
+ *
+ *  @return psMemProblemCallback       old psMemProblemCallback function
+ */
+psMemProblemCallback psMemProblemCallbackSet(
+    psMemProblemCallback func          ///< Function to run at memory problem detection
+);
+
+/** Set callback for out-of-memory.
+ *
+ *  If not enough memory is available to satisfy a request by psAlloc or 
+ *  psRealloc, these functions attempt to find an alternative solution by 
+ *  calling the psMemExhaustedCallback, a function which may be set by the 
+ *  programmer in appropriate circumstances, rather than immediately fail. 
+ *  The typical use of such a feature may be when a program needs a large 
+ *  chunk of memory to do an operation, but the exact size is not critical. 
+ *  This feature gives the programmer the opportunity to make a smaller 
+ *  request and try again, limiting the size of the operating buffer.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemExhaustedCallback     old psMemExhaustedCallback function
+ */
+psMemExhaustedCallback psMemExhaustedCallbackSet(
+    psMemExhaustedCallback func        ///< Function to run at memory exhaustion
+);
+
+/** Set call back for when a particular memory block is allocated
+ *
+ *  A private variable, p_psMemAllocateID, can be used to trace the allocation 
+ *  and freeing of specific memory blocks. If p_psMemAllocateID is set and a 
+ *  memory block with that ID is allocated, psMemAllocateCallback is called 
+ *  just before memory is returned to the calling function.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemAllocateCallback      old psMemAllocateCallback function
+ */
+psMemAllocateCallback psMemAllocateCallbackSet(
+    psMemAllocateCallback func       ///< Function to run at memory allocation of specific mem block
+);
+
+/** Set call back for when a particular memory block is freed
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of 
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with 
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemFreeCallback          old psMemFreeCallback function
+ */
+psMemFreeCallback psMemFreeCallbackSet(
+    psMemFreeCallback func             ///< Function to run at memory free of specific mem block
+);
+
+/** get next memory ID
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId                 the next memory ID to be used
+ */
+psMemoryId psMemGetId(void);
+
+/** set p_psMemAllocateID to specific id
+ *
+ *  A private variable, p_psMemAllocateID, can be used to trace the allocation 
+ *  and freeing of specific memory blocks. If p_psMemAllocateID is set and a 
+ *  memory block with that ID is allocated, psMemAllocateCallback is called 
+ *  just before memory is returned to the calling function.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId       
+ *
+ *  @see psMemAllocateCallbackSet    
+ */
+psMemoryId psMemAllocateCallbackSetID(
+    psMemoryId id                      ///< ID to set
+);
+
+/** set p_psMemFreeID to id
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of 
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with 
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @ingroup memCallback
+ *
+ *  @return psMemoryId                 the old p_psMemFreeID
+ *
+ *  @see psMemFreeCallbackSet
+ */
+psMemoryId psMemFreeCallbackSetID(
+    psMemoryId id                      ///< ID to set
+);
+
+//@} End of Memory Management Functions
+
+#ifndef DOXYGEN
+
+/*
+ * Ensure that any program using malloc/realloc/free will fail to compile
+ */
+#ifndef PS_ALLOW_MALLOC
+#ifdef __GNUC__
+#pragma GCC poison malloc realloc calloc free
+#else
+#define malloc(S)       _Pragma("error Use of malloc is not allowed.  Use psAlloc instead.")
+#define realloc(P,S)    _Pragma("error Use of realloc is not allowed.  Use psRealloc instead.")
+#define calloc(S)       _Pragma("error Use of calloc is not allowed.  Use psAlloc instead.")
+#define free(P)         _Pragma("error Use of free is not allowed.  Use psFree instead.")
+#endif
+#endif
+
+#endif
+// doxygen skip
+
+#endif // end of header file
Index: /tags/rel2_1/psLib/src/sysUtils/psString.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psString.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psString.c	(revision 1553)
@@ -0,0 +1,103 @@
+
+/** @file  psString.c
+ *
+ *  @brief Contains the definition of string utility functions
+ *
+ *  String utility functions defined shall provide basic string copying
+ *  capabilities while using the preferred memory management utilities.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *   
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-07 00:06:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "psString.h"
+#include "psMemory.h"
+#include "psError.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+char *psStringCopy(const char *str)
+{
+    // Allocate memory using psAlloc function
+    // Copy input string to memory just allocated
+    // Return the copy
+    return strcpy(psAlloc(strlen(str) + 1), str);
+}
+
+char *psStringNCopy(const char *str, int nChar)
+{
+    char *returnValue = NULL;
+
+    // Check the number of characters to copy is non-negative
+    if (nChar < 0) {
+        // Log error message and return NULL
+        psError(__FILE__, "psStringNCopy with negative count specified %d", nChar);
+        return NULL;
+    }
+    // Allocate memory using psAlloc function - nChar bytes
+    // Copy input string to memory allocated up to nChar characters
+    // Return the copy
+    returnValue = strncpy(psAlloc((size_t) nChar + 1), str, (size_t) nChar);
+
+    // Ensure the last byte is NULL character
+    if (nChar > 0) {
+        returnValue[nChar - 1] = '\0';
+    }
+    // Return the string pointer
+    return returnValue;
+}
Index: /tags/rel2_1/psLib/src/sysUtils/psString.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psString.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psString.h	(revision 1553)
@@ -0,0 +1,70 @@
+/** @file  psString.h
+ *
+ *  @brief Contains the declarations of string utility functions
+ *
+ *  @ingroup SysUtils
+ *
+ *  String utility functions defined shall provide basic string copying
+ *  capabilities.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-10 01:55:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_STRING_H
+#define PS_STRING_H
+
+
+/** This macro will convert the argument to a quoted string */
+#define PS_STRING(S)  #S
+
+// Doxygen group tags
+
+/** @addtogroup SysUtils
+ *  @{
+ */
+
+/** Copies the input string
+ *
+ *  This function shall allocate memory to the length of the input string
+ *  plus one and copy the input string to the newly allocated memory.
+ *
+ *  @return char*      Copy of input string
+ *
+ */
+char *psStringCopy(
+    const char *str
+    /**< Input string of characters to copy */
+);
+
+/** Copies the input string up to the specified number of characters
+ *
+ *  This function shall allocate memory to the length specified by nChar
+ *  plus one and copy the input string to the newly allocated memory.
+ *  This function will only copy nChar bytes from the input to new string,
+ *  so if the input string is larger than nChar characters the copied
+ *  string will be a substring of the input string.  If the input string
+ *  is smaller than nChar bytes then the remaining bytes allocated will
+ *  be set to NULL.
+ *
+ *  @return  char* Copy of input string
+ *
+ */
+
+/*@null@*/
+
+char *psStringNCopy(
+    const char *str,
+    /**< Input string of characters to copy */
+
+    int nChar
+    /**< Number of bytes to allocate for string copy */
+);
+
+/* @} */// Doxygen - End of SystemGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psTrace.c
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psTrace.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psTrace.c	(revision 1553)
@@ -0,0 +1,402 @@
+
+/** @file psTrace.c
+ *  \brief basic run-time trace facilities
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the code for procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************
+    NOTES:
+ In the SRD, higher trace levels correspond to a numerically lower trace
+ value in the code.  This is a bit confusing.  For example, a high-level
+ message might be something like "Begin Processing".  The module programmer
+ might give that a numerically low trace level, such as 1, so then any
+ non-zero trace level in that code component will display thatmessage.
+ 
+ We build a tree of trace components.  Every node in the tree has a
+ depth, which is it's distance from the root.  However, this is not
+ not the same thing as a node's "level", which corresponds to the
+ trace level of that node.
+ 
+ I added a function psTraceFree() which frees all nodes in the trace component
+ tree.  Previously, there had been no function in the API which accomplished
+ this purpose.
+ *****************************************************************************/
+
+#ifndef PS_NO_TRACE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "psMemory.h"
+#include "psTrace.h"
+#include "psString.h"
+#include "psError.h"
+
+static p_psComponent* p_psCroot = NULL; // The root of the trace component
+static FILE *p_psTraceFP = NULL;        // File destination for messages.
+
+static void componentFree(p_psComponent* comp);
+static p_psComponent* componentAlloc(const char *name, int level);
+
+/*****************************************************************************
+componentAlloc(): allocate memory for a new node, and initialize members.
+ *****************************************************************************/
+static p_psComponent* componentAlloc(const char *name, int level)
+{
+    p_psComponent* comp = psAlloc(sizeof(p_psComponent));
+
+    p_psMemSetDeallocator(comp, (psFreeFcn) componentFree);
+    comp->name = psStringCopy(name);
+    comp->level = level;
+    comp->n = 0;
+    comp->subcomp = NULL;
+    return comp;
+}
+
+/*****************************************************************************
+componentFree(): free the current node in the root tree, and all children
+nodes as well.
+ *****************************************************************************/
+static void componentFree(p_psComponent* comp)
+{
+    if (comp == NULL) {
+        return;
+    }
+
+    if (comp->subcomp != NULL) {
+        for (int i = 0; i < comp->n; i++) {
+            psFree(comp->subcomp[i]);
+        }
+        psFree(comp->subcomp);
+    }
+
+    psFree((char *)comp->name);
+}
+
+/*****************************************************************************
+initTrace(): simply initialize the component root tree.
+*****************************************************************************/
+static void initTrace(void)
+{
+    if (p_psCroot == NULL) {
+        p_psCroot = componentAlloc(".", PS_DEFAULT_TRACE_LEVEL);
+    }
+}
+
+/*****************************************************************************
+Set all trace levels to zero.
+ *****************************************************************************/
+void p_psTraceReset(p_psComponent* currentNode)
+{
+    int i = 0;
+
+    if (NULL == currentNode) {
+        return;
+    }
+
+    currentNode->level = 0;
+    for (i = 0; i < currentNode->n; i++) {
+        if (NULL == currentNode->subcomp[i]) {
+            psError(__func__,
+                    "Sub-component %d of node %s in the trace tree is NULL.\n", i, currentNode->name);
+        } else {
+            p_psTraceReset(currentNode->subcomp[i]);
+        }
+    }
+    return;
+}
+
+/*****************************************************************************
+Set all trace levels to zero.
+ *****************************************************************************/
+void psTraceReset()
+{
+    p_psTraceReset(p_psCroot);
+}
+
+/*****************************************************************************
+Free all nodes in the component tree.
+ *****************************************************************************/
+void psTraceFree()
+{
+    psFree(p_psCroot);
+}
+
+/*****************************************************************************
+componentAdd(): Adds the component named "addNodeName" to the root tree.
+ 
+NOTE: replace the call to strsep() with a call to strtok(), which conforms
+to ANSI-C.
+ *****************************************************************************/
+static void componentAdd(const char *addNodeName, int level)
+{
+    int i = 0;                  // Loop index variable.
+    char name[strlen(addNodeName) + 1]; // buffer for writeable copy.
+    char *pname = name;
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = p_psCroot;
+    int nodeExists = 0;
+
+    // Is this the root node? If so, simply set level and return.
+    if (strcmp(".", addNodeName) == 0) {
+        p_psCroot->level = level;
+        return;
+    }
+
+    if (addNodeName[0] != '.') {
+        printf("ERROR: failed to add %s to the root component tree.\n", addNodeName);
+        exit(1);
+    }
+
+    strcpy(name, addNodeName);
+    pname = &name[1];
+    // Iterate through the components of addNodeName.  Strip off the first
+    // component of the name, find that in the root tree, or add it if it
+    // does not exist, then move to the next component in the name.
+
+    while (pname != NULL) {
+        firstComponent = strsep(&pname, ".");
+        nodeExists = 0;
+        for (i = 0; i < currentNode->n; i++) {
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                nodeExists = 1;
+                if (pname == NULL) {
+                    currentNode->level = level;
+                }
+            }
+        }
+
+        if (nodeExists == 0) {
+            currentNode->subcomp = psRealloc(currentNode->subcomp,
+                                             (currentNode->n + 1) * sizeof(p_psComponent* ));
+            currentNode->n = (currentNode->n) + 1;
+
+            currentNode->subcomp[(currentNode->n) - 1] = componentAlloc(firstComponent, level);
+        }
+    }
+}
+
+/*****************************************************************************
+    psSetTraceLevel(): add the component named "comp" to the component tree,
+ if it is not already there, and set it's trace level to "level".
+    Input:
+ comp
+ level
+    Output:
+ none
+    Returns:
+ zero
+*****************************************************************************/
+int psTraceSetLevel(const char *comp,   // component of interest
+                    int level)  // desired trace level
+{
+    // If the root component tree does not exist, then initialize it.
+    if (p_psCroot == NULL) {
+        initTrace();
+    }
+    // Add the new component to the component tree.
+    componentAdd(comp, level);
+
+    // return 0 on success.
+    return 0;
+}
+
+/*****************************************************************************
+    doGetTraceLevel()
+ This function recursively searches the root component tree for the
+ component named "name", which is supplied by a parameter.  If it
+ finds that component, it returns the level of that component.
+ Otherwise, it returns ???.
+ 
+    Inputs:
+ name:
+    Outputs:
+ none
+    Returns:
+ The trace level of the "name" component.
+ *****************************************************************************/
+static int doGetTraceLevel(const char *aname)
+{
+    char name[strlen(aname) + 1];       // need a writeable copy: for strsep()
+    char *pname = name;
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = p_psCroot;
+    int i = 0;
+
+    if (NULL == currentNode) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    if (strcmp(".", aname) == 0) {
+        return (p_psCroot->level);
+    }
+
+    if (aname[0] != '.') {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    strcpy(name, aname);
+    pname = &name[1];
+    while (pname != NULL) {
+        firstComponent = strsep(&pname, ".");
+        for (i = 0; i < currentNode->n; i++) {
+            if (NULL == currentNode->subcomp[i]) {
+                psError(__func__,
+                        "Sub-component %d of node %s in trace tree is NULL.\n", i, currentNode->name);
+            }
+
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                if (pname == NULL) {
+                    return (currentNode->level);
+                }
+            }
+        }
+    }
+    return (PS_UNKNOWN_TRACE_LEVEL);
+}
+
+/*****************************************************************************
+    psGetTraceLevel()
+ Return a trace level of "name" in the root component tree.  If the
+ exact string of components in "name" does not exist in the root
+ tree, we return the deepest level of the match.
+    Input:
+ name
+    Output:
+ none
+    Return:
+ The level of "name" in the root component tree.
+ *****************************************************************************/
+int psTraceGetLevel(const char *name)
+{
+    if (p_psCroot == NULL) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+    // Search the component root tree, determine the trace level.
+    return (doGetTraceLevel(name));
+}
+
+/*****************************************************************************
+    doPrintTraceLevels()
+ This function recursively searches the component tree supplied by the
+ parameter "comp" and prints the name and level of each component.
+    Inputs:
+ comp: a node in the component tree.
+ level: the level of that node
+    Outputs:
+ none
+    Returns:
+ null
+ *****************************************************************************/
+static void doPrintTraceLevels(const p_psComponent* comp, int depth)
+{
+    int i = 0;
+
+    if (comp->name[0] == '\0') {
+        printf("%*s%-*s %d\n", depth, "", 20 - depth,
+               "(root)", (comp->level == PS_UNKNOWN_TRACE_LEVEL) ? 0 : comp->level);
+    } else {
+        if (comp->level == PS_UNKNOWN_TRACE_LEVEL) {
+            printf("%*s%-*s %s\n", depth, "", 20 - depth, comp->name, ".");
+        } else {
+            printf("%*s%-*s %d\n", depth, "", 20 - depth, comp->name, comp->level);
+        }
+    }
+
+    for (i = 0; i < comp->n; i++) {
+        doPrintTraceLevels(comp->subcomp[i], depth + 1);
+    }
+}
+
+/*****************************************************************************
+psPrintTraceLevels(): Simply print all the trace levels in the trace level
+component tree.
+Inputs:
+ none
+Outputs:
+ none
+Returns:
+ null
+*****************************************************************************/
+void psTracePrintLevels(void)
+{
+    if (p_psCroot == NULL) {
+        return;
+    }
+
+    doPrintTraceLevels(p_psCroot, 0);
+}
+
+/*****************************************************************************
+p_psTrace(): we display the trace message to standard output if the trace
+level of that message, supplied by the parameter "level" is higher than the
+trace level that is currently associated with the component named by the
+parameter "comp".
+Input:
+ comp
+ level
+ ...  a printf-style output string.
+Output:
+ none
+Return:
+ null
+ *****************************************************************************/
+void p_psTrace(const char *comp,        // component being traced
+               int level,       // desired trace level
+               ...)             // arguments
+{
+    char *fmt = NULL;
+    va_list ap;
+    int i = 0;
+
+    if (NULL == comp) {
+        psError(__func__, "p_psTrace() called on a NULL trace level tree\n");
+    }
+    // Only display this message if it's trace level is less than the level
+    // of it's associatedcomponent.
+    if (level <= psTraceGetLevel(comp)) {
+        va_start(ap, level);
+
+        // The following functions get the variable list of parameters with
+        // which this function was called, and print them to the standard
+        // output.
+        fmt = va_arg(ap, char *);
+
+        if (p_psTraceFP != NULL) {
+            // We indent each message one space for each level of the message.
+            for (i = 0; i < level; i++) {
+                fprintf(p_psTraceFP, " ");
+            }
+            vfprintf(p_psTraceFP, fmt, ap);
+        } else {
+            // We indent each message one space for each level of the message.
+            for (i = 0; i < level; i++) {
+                putchar(' ');
+            }
+            vprintf(fmt, ap);
+        }
+        va_end(ap);
+    }
+    // NOTE: should we free *fmt as well? Read the man page.
+}
+
+void psTraceSetDestination(FILE * fp)
+{
+    p_psTraceFP = fp;
+}
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psTrace.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psTrace.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psTrace.h	(revision 1553)
@@ -0,0 +1,93 @@
+
+/** @file psTrace.h
+ *  \brief basic run-time trace facilities
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the prototypes for defining procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_TRACE_H)
+#define PS_TRACE_H 1
+
+#define PS_UNKNOWN_TRACE_LEVEL -9999   // we don't know this name's level
+#define PS_DEFAULT_TRACE_LEVEL 0
+
+/** \addtogroup LogTrace
+ *  \{
+ */
+
+/** Functions **************************************************************/
+
+//#define PS_NO_TRACE 1   ///< to turn off all tracing
+
+#if defined(PS_NO_TRACE)
+#        define psTrace(facil, level, ...) (void)0
+/* do nothing */
+#        define p_psTrace(facil, level, ...)  (void)0
+/* do nothing */
+#        define psTraceSetLevel(facil,level) 0
+#        define psTraceGetLevel(facil) 0
+#        define psTraceReset() (void)0     /* do nothing */
+#        define psTraceFree() (void)0      /* do nothing */
+#        define psTracePrintLevels() (void)0
+/* do nothing */
+#        define psTraceSetDestination(fp) (void)0
+/* do nothing */
+#    else
+
+    /** Basic structure for the component tree.  A component is a string of the
+        form aaa.bbb.ccc, and may itself contain further subcomponents.  The
+        Component structure doesn't in fact contain it's full name, but only the
+        last part. */
+    typedef struct p_psComponent
+    {
+        const char *name;           // last part of name of component
+        int level;                  // trace level for this component
+        int n;                      // number of subcomponents
+        struct p_psComponent* *subcomp;     // next level of subcomponents
+    }
+p_psComponent;
+
+#ifndef DOXYGEN
+/// Send a trace message
+void p_psTrace(const char *facil,       ///< facilty of interest
+               int myLevel,     ///< desired trace level
+               ...)             ///< trace message arguments
+;
+#endif
+
+/// Set trace level
+int psTraceSetLevel(const char *facil,     ///< facilty of interest
+                    int level)     ///< desired trace level
+;
+
+/// Get the trace level
+int psTraceGetLevel(const char *facil)     ///< facilty of interest
+;
+
+/// Set all trace levels to zero (do not free nodes in the component tree).
+void psTraceReset();
+
+/// Free all nodes in the component tree.
+void psTraceFree();
+
+/// print trace levels
+void psTracePrintLevels(void);
+
+/// Set the destination of future trace messages.
+void psTraceSetDestination(FILE * fp);
+
+/* \} */// End of SystemGroup Functions
+
+#define psTrace(facil, level, ...) p_psTrace(facil, level, __VA_ARGS__)
+#endif
+
+#endif
Index: /tags/rel2_1/psLib/src/sysUtils/psType.h
===================================================================
--- /tags/rel2_1/psLib/src/sysUtils/psType.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/sysUtils/psType.h	(revision 1553)
@@ -0,0 +1,156 @@
+
+/** @file  psType.h
+*
+*  @brief Contains support for basic types
+*
+*  This file defines common datatypes used throughout psLib.
+*
+*  @ingroup DataContainer
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-10 01:55:34 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_TYPE_H
+#define PS_TYPE_H
+
+#include <complex.h>
+#include <stdint.h>
+#include <float.h>
+
+/// @addtogroup DataContainer
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Basic data types used by the containers.
+ *
+ * The basic types of the primitives used by psLib are defined within this enum. This enum is in turn used by
+ * the psType struct.
+ *
+ */
+
+typedef uint8_t psU8;                  ///< 8-bit unsigned int
+typedef uint16_t psU16;                ///< 16-bit unsigned int
+typedef uint32_t psU32;                ///< 32-bit unsigned int
+typedef uint64_t psU64;                ///< 64-bit unsigned int
+typedef int8_t psS8;                   ///< 8-bit signed int
+typedef int16_t psS16;                 ///< 16-bit signed int
+typedef int32_t psS32;                 ///< 32-bit signed int
+typedef int64_t psS64;                 ///< 64-bit signed int
+typedef float psF32;                   ///< 32-bit floating point
+typedef double psF64;                  ///< 64-bit floating point
+typedef complex float psC32;           ///< complex with 32-bit floating point Real and Imagary numbers
+typedef complex double psC64;          ///< complex with 64-bit floating point Real and Imagary numbers
+typedef void *psPTR;                   ///< void pointer
+
+typedef enum {
+    PS_TYPE_S8 = 0x0101,               ///< Character.
+    PS_TYPE_S16 = 0x0102,              ///< Short integer.
+    PS_TYPE_S32 = 0x0104,              ///< Integer.
+    PS_TYPE_S64 = 0x0108,              ///< Long integer.
+    PS_TYPE_U8 = 0x0301,               ///< Unsigned character.
+    PS_TYPE_U16 = 0x0302,              ///< Unsigned short integer.
+    PS_TYPE_U32 = 0x0304,              ///< Unsigned integer.
+    PS_TYPE_U64 = 0x0308,              ///< Unsigned long integer.
+    PS_TYPE_F32 = 0x0404,              ///< Single-precision Floating point.
+    PS_TYPE_F64 = 0x0408,              ///< Double-precision floating point.
+    PS_TYPE_C32 = 0x0808,              ///< Complex numbers consisting of single-precision floating point.
+    PS_TYPE_C64 = 0x0810,              ///< Complex numbers consisting of double-precision floating point.
+    PS_TYPE_PTR = 0x0000               ///< Something else that's not supported for arithmetic.
+} psElemType;
+
+#define PS_TYPE_MASK PS_TYPE_U8        /**< the psElemType to use for mask image */
+#define PS_TYPE_MASK_DATA U8           /**< the data member to use for mask image */
+#define PS_TYPE_MASK_NAME "psU8"       /**< the data type for mask as a string */
+
+typedef psU8 psMaskType;               ///< the C datatype for a mask image
+
+
+#define PS_MIN_S8        INT8_MIN      /**< minimum valid psS8 value */
+#define PS_MIN_S16       INT16_MIN     /**< minimum valid psS16 value */
+#define PS_MIN_S32       INT32_MIN     /**< minimum valid psS32 value */
+#define PS_MIN_S64       INT64_MIN     /**< minimum valid psS64 value */
+#define PS_MIN_U8        0             /**< minimum valid psU8 value */
+#define PS_MIN_U16       0             /**< minimum valid psU16 value */
+#define PS_MIN_U32       0             /**< minimum valid psU32 value */
+#define PS_MIN_U64       0             /**< minimum valid psU64 value */
+#define PS_MIN_F32       -FLT_MAX      /**< minimum valid psF32 value */
+#define PS_MIN_F64       -DBL_MAX      /**< minimum valid psF64 value */
+#define PS_MIN_C32       -FLT_MAX      /**< minimum valid real or imaginary psC32 value */
+#define PS_MIN_C64       -DBL_MAX      /**< minimum valid real or imaginary psC32 value */
+
+#define PS_MAX_S8        INT8_MAX      /**< maximum valid psS8 value */
+#define PS_MAX_S16       INT16_MAX     /**< maximum valid psS16 value */
+#define PS_MAX_S32       INT32_MAX     /**< maximum valid psS32 value */
+#define PS_MAX_S64       INT64_MAX     /**< maximum valid psS64 value */
+#define PS_MAX_U8        UINT8_MAX     /**< maximum valid psU8 value */
+#define PS_MAX_U16       UINT16_MAX    /**< maximum valid psU16 value */
+#define PS_MAX_U32       UINT32_MAX    /**< maximum valid psU32 value */
+#define PS_MAX_U64       UINT64_MAX    /**< maximum valid psU64 value */
+#define PS_MAX_F32       FLT_MAX       /**< maximum valid psF32 value */
+#define PS_MAX_F64       DBL_MAX       /**< maximum valid psF64 value */
+#define PS_MAX_C32       FLT_MAX       /**< maximum valid real or imaginary psC32 value */
+#define PS_MAX_C64       DBL_MAX       /**< maximum valid real or imaginary psC32 value */
+
+/// Macro to get the bad pixel reason code (stored as part of mask value)
+#define PS_BADPIXEL_BITMASK 0x0f
+#define PS_GET_BADPIXEL(maskValue) (maskValue & PS_BADPIXEL_BITMASK)
+
+#define PS_IS_BADPIXEL(maskValue) (PS_GET_BADPIXEL(maskValue) != 0)
+
+/// Macro to apply a bad pixel reason code to mask image
+#define PS_SET_BADPIXEL(maskValue, reasonCode) \
+{ \
+    maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \
+}
+
+/// Macro to determine if the psElemType is an integer.
+#define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100)
+/// Macro to determine if the psElemType is unsigned.
+#define PS_IS_PSELEMTYPE_UNSIGNED(x) ((x & 0x200) == 0x200)
+/// Macro to determine if the psElemType is a real (non-complex) floating-point type.
+#define PS_IS_PSELEMTYPE_REAL(x) ((x & 0x400) == 0x400)
+/// Macro to determine if the psElemType is complex number type.
+#define PS_IS_PSELEMTYPE_COMPLEX(x) ((x & 0x800) == 0x800)
+/// Macro to determine the storage size, in bytes, of the psElemType.
+#define PSELEMTYPE_SIZEOF(x) ( (x==PS_TYPE_PTR) ? sizeof(void*) :(x & 0xFF) )
+
+/** Dimensions of a data type.
+ *
+ * The dimensions of containers used by psLib are defined within this enum. This enum is used by the psType
+struct. *
+ */
+typedef enum {
+    PS_DIMEN_SCALAR,            ///< Scalar.
+    PS_DIMEN_VECTOR,            ///< Vector.
+    PS_DIMEN_TRANSV,            ///< Transposed vector.
+    PS_DIMEN_IMAGE,             ///< Image.
+    PS_DIMEN_OTHER              ///< Something else that's not supported for arithmetic.
+} psDimen;
+
+/** The type of a data type.
+ *
+ * All psLib complex types consist of primitive components. This struct provides the description of those
+ * primitives.
+ *
+ */
+typedef struct
+{
+    psElemType type;            ///< Primitive type.
+    psDimen dimen;              ///< Dimensionality.
+}
+psType;
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/types/psArray.c
===================================================================
--- /tags/rel2_1/psLib/src/types/psArray.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psArray.c	(revision 1553)
@@ -0,0 +1,122 @@
+
+/** @file  psArray.c
+ *
+ *  @brief Contains support for basic vector types
+ *
+ *  This file defines the basic type for a vector struct and functions useful
+ *  in manupulating vectors.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include<stdlib.h>                         // for qsort, etc.
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psArray.h"
+#include "psLogMsg.h"
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void arrayFree(psArray* restrict psArr);
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psArray* psArrayAlloc(unsigned int nalloc)
+{
+    psArray* psArr = NULL;
+
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);
+        return NULL;
+    }
+    // Create vector struct
+    psArr = (psArray* ) psAlloc(sizeof(psArray));
+    p_psMemSetDeallocator(psArr, (psFreeFcn) arrayFree);
+
+    psArr->nalloc = nalloc;
+    psArr->n = nalloc;
+
+    // Create vector data array
+    psArr->data = psAlloc(nalloc * sizeof(psPTR));
+
+    return psArr;
+}
+
+psArray* psArrayRealloc(unsigned int nalloc, psArray* restrict in)
+{
+    // Invalid nalloc
+    if (nalloc < 1) {
+        psError(__func__, "Invalid value for realloc (%d)\n", nalloc);
+        return NULL;
+    }
+
+    if (in == NULL) {
+        psError(__func__, "Null input vector\n");
+        return NULL;
+    } else if (in->nalloc != nalloc) {     // No need to realloc to same size
+        if (nalloc < in->n) {
+            for (int i = nalloc; i < in->n; i++) {      // For reduction in vector size
+                psFree(in->data[i]);
+            }
+            in->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        in->data = psRealloc(in->data, nalloc * sizeof(psPTR));
+        in->nalloc = nalloc;
+    }
+
+    return in;
+}
+
+static void arrayFree(psArray* restrict psArr)
+{
+    if (psArr == NULL) {
+        return;
+    }
+
+    psArrayElementFree(psArr);
+
+    psFree(psArr->data);
+}
+
+void psArrayElementFree(psArray* restrict psArr)
+{
+
+    if (psArr == NULL) {
+        return;
+    }
+
+    for (int i = 0; i < psArr->n; i++) {
+        psFree(psArr->data[i]);
+        psArr->data[i] = NULL;
+    }
+}
+
+psArray* psArraySort(psArray* in, psComparePtrFcn compare)
+{
+    if (in == NULL) {
+        return NULL;
+    }
+
+    qsort(in->data, in->n, sizeof(psPTR), (int (*)(const void *, const void *))compare);
+
+    return in;
+}
Index: /tags/rel2_1/psLib/src/types/psArray.h
===================================================================
--- /tags/rel2_1/psLib/src/types/psArray.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psArray.h	(revision 1553)
@@ -0,0 +1,105 @@
+
+/** @file  psArray.h
+ *
+ *  @brief Contains basic array definitions and operations
+ *
+ *  This file defines the basic type for a array struct and functions useful
+ *  in manupulating arrays.
+ *
+ *  @ingroup Array
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:47:31 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ARRAY_H
+#define PS_ARRAY_H
+
+#include "psType.h"
+#include "psCompare.h"
+
+/// @addtogroup Array
+/// @{
+
+/** An array to support primitive types.
+ *
+ * Struct for maintaining an array of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    unsigned int nalloc;        ///< Total number of elements available.
+    unsigned int n;             ///< Number of elements in use.
+    psPTR* data;                ///< An Array of pointer elements
+}
+psArray;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate an array.
+ *
+ * Uses psLib memory allocation functions to create an array collection of 
+ * data
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+psArray* psArrayAlloc(
+    unsigned int nalloc                ///< Total number of elements to make available.
+);
+
+/** Reallocate an array.
+ *
+ * Uses psLib memory allocation functions to reallocate an array collection 
+ * of data. 
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+psArray* psArrayRealloc(
+    unsigned int nalloc,               ///< Total number of elements to make available.
+    psArray* restrict psArr            ///< array to reallocate.
+);
+
+/** Deallocate/Dereference elements of an array.
+ *
+ * Uses psLib memory allocation functions to deallocate/dereference elements 
+ * of a array of void pointers.  The array psArr is not freed, and its elements
+ * will all be set to NULL.
+ *
+ */
+void psArrayElementFree(
+    psArray* restrict psArr            ///< Void pointer array to destroy.
+);
+
+/** Sort the array according to an external compare function.
+ *
+ *  Sorts an array via the specification of a comparison function
+ *  to specify how the objects on the array should be sorted.
+ *
+ *  The comparison function must return an integer less than, equal to, or 
+ *  greater than zero if the first argument is considered to be respectively 
+ *  less than, equal to, or greater than the second. 
+ *
+ *  If two members compare as equal, their order in the sorted array is 
+ *  undefined.
+ *
+ *  @return psArray* The sorted array.
+ */
+psArray* psArraySort(
+    psArray* in,                       ///< input array to sort.
+    psComparePtrFcn compare            ///< the compare function
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/types/psBitSet.c
===================================================================
--- /tags/rel2_1/psLib/src/types/psBitSet.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psBitSet.c	(revision 1553)
@@ -0,0 +1,297 @@
+
+/** @file  psBitSet.c
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:34:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdbool.h>
+
+#include "psBitSet.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+
+/******************************************************************************/
+
+/*  DEFINE STATEMENTS                                                         */
+
+/******************************************************************************/
+
+// None
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  GLOBAL VARIABLES                                                         */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FILE STATIC VARIABLES                                                    */
+
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+
+/*****************************************************************************/
+static void psBitSetFree(psBitSet* restrict inBitSet);
+
+/** Private function to create a mask.
+ *
+ *  Creates an eight bit mask with the given bit set. All other bits in the byte are zero. The input bit uses
+ *  zero-based indexing, and is the cumulitive index within the array, not the localized byte's bit position.
+ *
+ *  @return  char*: Pointer to byte in which bit is contained.
+ */
+static char mask(int bit)
+{
+    char mask = (char)0x01;
+
+    // Ignore splint warning about negative bit shifts
+    /* @i@ */
+    mask = mask << (bit % 8);
+
+    return mask;
+}
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+psBitSet* psBitSetAlloc(int n)
+{
+    int numBytes = 0;
+    psBitSet* newObj = NULL;
+
+    if (n <= 0) {
+        psError(__func__, " : Line %d - Allocation size must be > 0: size = %d", __LINE__, n);
+        return 0;
+    }
+
+    numBytes = ceil(n / 8.0);
+    newObj = psAlloc(sizeof(psBitSet));
+    if (newObj == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+    p_psMemSetDeallocator(newObj, (psFreeFcn) psBitSetFree);
+    newObj->n = numBytes;
+
+    // Ignore splint warning about releasing pointer members, since they've not been allocated yet
+    /* @i@ */
+    newObj->bits = psAlloc(sizeof(char) * numBytes);
+    if (newObj->bits == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    memset(newObj->bits, numBytes, 0);
+
+    return newObj;
+}
+
+static void psBitSetFree(psBitSet* restrict inBitSet)
+{
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return;
+    }
+    psFree(inBitSet->bits);
+}
+
+psBitSet* psBitSetSet(psBitSet* inBitSet, int bit)
+{
+    char *byte = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return inBitSet;
+    } else if (bit < 0) {
+        psError(__func__, " : Line %d - Bit position too small: %d", __LINE__, bit);
+        return inBitSet;
+    } else if (bit > inBitSet->n * 8 - 1) {
+        psError(__func__, " : Line %d - Bit position too large: %d", __LINE__, bit);
+        return inBitSet;
+    }
+    // Variable byte is the byte in the array that contains the bit to be set
+    byte = inBitSet->bits + bit / 8;
+    *byte |= mask(bit);
+
+    return inBitSet;
+}
+
+bool psBitSetTest(const psBitSet* inBitSet, int bit)
+{
+    char *byte = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return 0;
+    } else if (bit < 0) {
+        psError(__func__, " : Line %d - Bit position too small: %d", __LINE__, bit);
+        return 0;
+    } else if (bit > inBitSet->n * 8 - 1) {
+        psError(__func__, " : Line %d - Bit position too large: %d", __LINE__, bit);
+        return 0;
+    }
+    // Variable byte is the byte in the array that contains the bit to be tested
+    byte = inBitSet->bits + bit / 8;
+    if ((int)(*byte & mask(bit)) == 0) {
+        return 0;
+    }
+
+    return 1;
+}
+
+psBitSet* psBitSetOp(psBitSet* outBitSet, const psBitSet* restrict inBitSet1, char *operator,
+                     const psBitSet* restrict inBitSet2)
+{
+    int i = 0;
+    int n = 0;
+    char tempChar = '0';
+    char *outBits = NULL;
+    char *inBits1 = NULL;
+    char *inBits2 = NULL;
+
+    if (inBitSet1 == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet1 argument", __LINE__);
+        return outBitSet;
+    }
+
+    if (operator == NULL) {
+        psError(__func__, " : Line %d - Null input operator\n", __LINE__);
+        return outBitSet;
+    }
+
+    if (inBitSet2 == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet2 argument", __LINE__);
+        return outBitSet;
+    }
+
+    if (outBitSet == NULL) {
+        outBitSet = psBitSetAlloc(inBitSet1->n * 8);
+    }
+
+    if (inBitSet1->n != inBitSet2->n || outBitSet->n != inBitSet1->n) {
+        psError(__func__, " : Line %d - psBitSet sizes not the same", __LINE__);
+        return outBitSet;
+    }
+
+    n = outBitSet->n;
+    outBits = outBitSet->bits;
+    inBits1 = inBitSet1->bits;
+    inBits2 = inBitSet2->bits;
+
+    tempChar = toupper(operator[0]);
+    switch (tempChar) {
+    case 'A':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] & inBits2[i];
+        }
+        break;
+    case 'O':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] | inBits2[i];
+        }
+        break;
+    case 'X':
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] ^ inBits2[i];
+        }
+        break;
+    default:
+        psError(__func__, " : Line %d - Invalid psBitMask binary operation: %s", __LINE__, operator);
+    }
+
+    return outBitSet;
+}
+
+psBitSet* psBitSetNot(psBitSet* outBitSet, const psBitSet* restrict inBitSet)
+{
+    int i = 0;
+    int n = 0;
+    char *outBits = NULL;
+    char *inBits = NULL;
+
+    if (inBitSet == NULL) {
+        psError(__func__, " : Line %d - Null psBitSet for inBitSet argument", __LINE__);
+        return outBitSet;
+    }
+
+    n = inBitSet->n;
+    if (n == 0) {
+        psError(__func__, " : Line %d - No elements in inBitSet", __LINE__);
+        return outBitSet;
+    }
+
+    if (outBitSet == NULL) {
+        outBitSet = psBitSetAlloc(n * 8);
+    }
+
+    if (inBitSet->n != outBitSet->n) {
+        psError(__func__, " : Line %d - psBitSet sizes not the same", __LINE__);
+        return outBitSet;
+    }
+
+    outBits = outBitSet->bits;
+    inBits = inBitSet->bits;
+
+    for (i = 0; i < n; i++) {
+        outBits[i] = ~inBits[i];
+    }
+
+    return outBitSet;
+}
+
+char *psBitSetToString(const psBitSet* restrict inBitSet)
+{
+    int i = 0;
+    int numBits = inBitSet->n * 8;
+    char *outString = psAlloc((size_t) numBits + 1);
+
+    if (outString == NULL) {
+        psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
+    }
+
+    for (i = 0; i < numBits; i++) {
+        outString[numBits - i - 1] = (psBitSetTest(inBitSet, i) == 1) ? '1' : '0';
+    }
+
+    outString[numBits] = 0;
+
+    return outString;
+}
Index: /tags/rel2_1/psLib/src/types/psBitSet.h
===================================================================
--- /tags/rel2_1/psLib/src/types/psBitSet.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psBitSet.h	(revision 1553)
@@ -0,0 +1,134 @@
+
+/** @file  psBitSet.h
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @ingroup BitSet
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 19:53:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSBITSET_H
+#define PSBITSET_H
+
+/// @addtogroup BitSet
+/// @{
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Struct containing array of bytes to hold bit data and corresponding array length.
+ *
+ *  The bits in the struct are assembled in as an array of bytes with eight bits per byte. The bits are
+ *  arranged with the LSB in first (right most) position of the first array element.
+ */
+typedef struct
+{
+    int n;                             ///< Number of bytes in the array
+    char *bits;                        ///< Aray of bytes holding bits
+}
+psBitSet;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a psBitSet.
+ *
+ *  Create a psBitSet with the number of bits specified by the user. All bits are set to zero upon
+ *  allocation.
+ *
+ *  @return  psBitSet* : Pointer to struct containing array of bits and size of array.
+ */
+
+/*@null@*/
+psBitSet* psBitSetAlloc(
+    int n                              ///< Number of bits in psBitSet array
+);
+
+/** Set a bit.
+ *
+ *  Sets a bit at a given bit location, either one or zero. The bit is set based on a zero index with the
+ *  first bit set in the zero bit slot of the zero element of the byte array. As an example, setting bit 3 in
+ *  an array with two elements would result in an psBitSet that looks like 00000000 00001000.
+ *
+ *  @return  psBitSet* : Pointer to struct containing psBitSet.
+ */
+psBitSet* psBitSetSet(
+    /* @returned@ */
+    psBitSet* restrict inMask,         ///< Pointer to psBitSet to be set.
+    int bit                            ///< Bit to be set.
+);
+
+/** Test the value of a bit.
+ *
+ *  Prints the value of a bit at a given bit location, either one or zero. The resulting bit is based on a
+ *  zero index format with the first bit set in the zero bit slot of the zero element of the byte array
+ *  As an example, testing bit 3 in a psBitSet with two bytes that looks like 00000000 00001000 would return a
+ *  value of one, since that is the value that was set.
+ *
+ *  @return  int: Value of bit, either one or zero.
+ */
+
+bool psBitSetTest(
+    const psBitSet* restrict inMask,   ///< Pointer psBitSet to be tested.
+    int bit                            ///< Bit to be tested.
+);
+
+/** Perform a binary operation on two psBitSets
+ *
+ *  Perform an AND, OR, or XOR on two psBitSets. If the BitMasks are not the same size, the operation will not
+ *  be performed and an error message will be logged.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of binary operation.
+ */
+psBitSet* psBitSetOp(
+    /* @returned@ */
+    psBitSet* restrict outMask,        ///< Resulting psBitSet from binary operation
+    const psBitSet* restrict inMask1,  ///< First psBitSet on which to operate
+    char *operator,                    ///< Bit operation
+    const psBitSet* restrict inMask2   ///< First psBitSet on which to operate
+);
+
+/** Perform a not operation on a psBitSet
+ *
+ *  Toggles bits in a psBitset. All zero bits are set to one and all one bits are set to zero.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of operation.
+ */
+
+psBitSet* psBitSetNot(
+    psBitSet* outBitSet,               ///< Resulting psBitSet from operation
+    const psBitSet* restrict inBitSet  ///< Input psBitSet
+);
+
+/** Convert the psBitSet to a string of ones and zeros.
+ *
+ *  Converts the contents of a psBitSet to a string representation of its binary form of ones and zeros. The
+ *  LSB is the right-most chracter. Each set of eight characters represents one byte.
+ *
+ *  @return  char*: Pointer to character array containing string data.
+ */
+
+char *psBitSetToString(
+    const psBitSet* restrict inMask    ///< psBitSet to convert */
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/src/types/psHash.c
===================================================================
--- /tags/rel2_1/psLib/src/types/psHash.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psHash.c	(revision 1553)
@@ -0,0 +1,408 @@
+
+/** @file  psHash.c
+*
+*  @brief Contains support for basic hashing functions.
+*
+*  This file will hold the functions for defining a hash table with arbitrary
+*  data types, allocating/deallocating that hash table, adding and removing
+*  data from that hash table, and listing all keys defined in the hash table.
+*
+*  @author Robert Lupton, Princeton University
+*  @author George Gusciora, MHPCC
+*
+*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-09 23:34:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include "psHash.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psTrace.h"
+#include "psAbort.h"
+
+static psHashBucket* hashBucketAlloc(const char *key, void *data, psHashBucket* next);
+static void hashBucketFree(psHashBucket* bucket);
+static void *doHashWork(psHash* table, const char *key, void *data, bool remove
+                           );
+static void hashFree(psHash* table);
+
+/******************************************************************************
+psHashKeyList(table): this function creates a linked list with an entry in
+that list for every key in the hash table.
+Inputs:
+    table: a hash table
+Return;
+    The linked list
+ *****************************************************************************/
+psList* psHashKeyList(psHash* table)
+{
+    int i = 0;                  // Loop index variable
+    psList* myLinkList = NULL;  // The output data structure
+    psHashBucket* ptr = NULL;   // Used to step thru linked list.
+
+    if (table == NULL) {
+        return NULL;
+    }
+    // Create the linked list
+    myLinkList = psListAlloc(NULL);
+
+    // Loop through every bucket in the hash table.  If that bucket is not
+    // NULL, then add the bucket's key to the linked list.
+    for (i = 0; i < table->nbucket; i++) {
+        if (table->buckets[i] != NULL) {
+            // Since a bucket contains a linked list of keys/data, we must
+            // step trough each key in that linked list:
+
+            ptr = table->buckets[i];
+            while (ptr != NULL) {
+                psListAdd(myLinkList, ptr->key, PS_LIST_HEAD);
+                ptr = ptr->next;
+            }
+        }
+    }
+
+    // Return the linked list
+    return (myLinkList);
+}
+
+/******************************************************************************
+hashBucketAlloc(key, data, next): This procedure creates a new hash bucket
+with the specified key, data, and next.
+Inputs:
+    key:  the new bucket's key pointer
+    data: the new bucket's data pointer
+    next: the new bucket's key pointer
+Return:
+    the new hash bucket.
+ *****************************************************************************/
+static psHashBucket* hashBucketAlloc(const char *key, void *data, psHashBucket* next)
+{
+    if (key == NULL) {
+        psAbort(__func__, "psHashBucket() called with NULL key.");
+    }
+    // Allocate memory for the new hash bucket.
+    psHashBucket* bucket = psAlloc(sizeof(psHashBucket));
+
+    p_psMemSetDeallocator(bucket, (psFreeFcn) hashBucketFree);
+
+    // Initialize the bucket.
+    bucket->key = psStringCopy(key);
+
+    if (data == NULL) {
+        // NOTE: Should we flag a warning message?
+        bucket->data = NULL;
+    } else {
+        bucket->data = psMemIncrRefCounter(data);
+    }
+
+    bucket->next = next;
+
+    return bucket;
+}
+
+/******************************************************************************
+hashBucketFree(bucket): This procedure deallocates the specified
+hash bucket.
+Inputs:
+    bucket: the hash bucket to be freed.
+Return:
+    NONE
+ *****************************************************************************/
+static void hashBucketFree(psHashBucket* bucket)
+{
+    if (bucket == NULL) {
+        return;
+    }
+
+    psFree(bucket->key);
+
+    psFree(bucket->data);
+}
+
+/******************************************************************************
+psHashAlloc(nbucket): this procedure creates a new hash table with the
+specified number of buckets.
+Inputs:
+    nbucket: initial number of buckets
+Return:
+    The new hash table.
+ *****************************************************************************/
+psHash* psHashAlloc(int nbucket)        // initial number of buckets
+{
+    int i = 0;                  // loop index variable
+
+    // Create the new hash table.
+    psHash* table = psAlloc(sizeof(psHash));
+
+    p_psMemSetDeallocator(table, (psFreeFcn) hashFree);
+
+    // Allocate memory for the buckets.
+    table->buckets = psAlloc(nbucket * sizeof(psHashBucket* ));
+    table->nbucket = nbucket;
+
+    psTrace("utils.hash", 1, "Creating %d-element hash table\n", nbucket);
+
+    // Initialize all buckets to NULL.
+    for (i = 0; i < nbucket; i++)
+    {
+        table->buckets[i] = NULL;
+    }
+
+    // Return the new hash table.
+    return table;
+}
+
+/******************************************************************************
+psHashFree(table, itemFree): This procedure deallocates the specified hash
+table.  It loops through each bucket, and calls hashBucketFree() on that
+bucket.
+ 
+Inputs:
+    table: a hash table
+Return:
+    NONE
+ *****************************************************************************/
+static void hashFree(psHash* table)
+{
+    int i = 0;                  // Loop index variable.
+
+    if (table == NULL) {
+        return;
+    }
+    // Loop through each bucket in the hash table.  If that bucket is not
+    // NULL, then free the bucket via a function call to hashBucketFree();
+    for (i = 0; i < table->nbucket; i++) {
+
+        // A bucket is composed of a linked list of buckets.
+        while (table->buckets[i] != NULL) {
+            psHashBucket* bucket = table->buckets[i];
+            table->buckets[i] = bucket->next;
+            psFree(bucket);
+        }
+    }
+
+    // Free the bucket structure, then the hash table.
+    psFree(table->buckets);
+}
+
+/******************************************************************************
+doHashWork(table, key, data, remove): This is an internal
+procedure which does the bulk of the work in using the hash table.  Depending
+upon the input parameters, it will either insert a new key/data into the hash
+table, retrieve the data for a specified key, or remove a key/data item.  If
+we try to insert a key that already exists in the hash table, then we deallocate
+the existing data/key item.
+Inputs:
+    table: a hash table
+    key: the key to insert, retrieve, or remove.  Must not be NULL.
+    data: the data to insert, if not NULL
+    remove: set to non-zero if the key/data should be removed from the table.
+Return:
+    NONE
+ 
+NOTE: consider removing this private function and simply putting the code
+into the psHashInsert(), psHashLookup(), and psHashRemove().  Why?  Because
+there is little common code between those functions.
+  *****************************************************************************/
+static void *doHashWork(psHash* table, const char *key, void *data, bool remove
+                           )
+{
+    long int hash = 1;          // This will contain an integer value
+
+    // "hashed" from the key.
+    char *tmpchar = NULL;       // Used in computing the hash function.
+    psHashBucket* ptr = NULL;   // Used to retrieve the hash bucket.
+    psHashBucket* optr = NULL;  // "original pointer": used to step
+
+    // thru the linked list for a bucket.
+
+    // The following condition should never be true, since this is a private
+    // function, but I'm checking it anyway since future coders might change
+    // the way this procedure is called.
+    if ((table == NULL) || (key == NULL)) {
+
+        psAbort(__func__, "psHashRemove() called with NULL key or table.");
+    }
+    // NOTE: This is the originally supplied hash function.
+    // for (int i = 0, len = strlen(key); i < len; i++) {
+    // hash = (hash << 1) ^ key[i];
+    // }
+    // hash &= (table->nbucket - 1);
+
+    // This hash algorithm is from Sedgewick.  NOTE: must reread to ensure that
+    // the size of the hash table is not required to be a prime number.
+    tmpchar = (char *)key;
+    for (hash = 0; *tmpchar != '\0'; tmpchar++) {
+        hash = (64 * hash + *tmpchar) % (table->nbucket);
+    }
+
+    // NOTE: This should not be necessary, but for now, I'm checking bounds
+    // anyway.
+    if ((hash < 0) || (hash >= table->nbucket)) {
+        psAbort(__func__, "Internal hash function out of range (%d)", hash);
+    }
+    // ptr will have the correct hash bucket.
+    ptr = table->buckets[hash];
+
+    // We know the correct hash bucket, now we need to know what to do.
+    // If the data parameter is NULL, then, by definition, this is a retrieve
+    // or a remove operation on the hash table.
+
+    if (data == NULL) {
+        if (remove
+           ) {
+            // We search through the linked list for this bucket in
+            // the hash table and look for an entry for this key.
+
+            optr = ptr;
+            while (ptr != NULL) {
+                // Determine if this entry holds the correct key.
+                if (strcmp(key, ptr->key) == 0) {
+                    // The following lines of code are fairly standard ways
+                    // of removing an item from a single-linked list.
+
+                    void *data = ptr->data;
+
+                    optr->next = ptr->next;
+                    if (ptr == table->buckets[hash]) {
+                        table->buckets[hash] = ptr->next;
+                    }
+                    psFree(ptr);
+
+                    // By definition, the data associated with that key
+                    // must be returned, not freed.
+                    return data;
+                }
+                optr = ptr;
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+        else {
+            // If we get here, then a retrieve operation is requested.  So,
+            // we step trough the linked list at this bucket, and return the
+            // data once we find it, or return NULL if we don't.
+            while (ptr != NULL) {
+                if (strcmp(key, ptr->key) == 0) {
+                    return ptr->data;
+                }
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+    } else {
+        // We get here if this procedure was called with non-NULL data.
+        // Therefore, we should insert that data into the hash table.
+        // First, we search through the linked list for this bucket in
+        // the hash table and look for a duplicate entry for this key.
+
+        while (ptr != NULL) {
+            if (strcmp(key, ptr->key) == 0) {
+                // We have found this key in the hash table.
+
+                psTrace("utils.hash.insert", 3, "Replacing data for %s\n", key);
+
+                // NOTE: I have changed this behavior from the originally
+                // supplied code.  Formerly, if itemFree was NULL, then
+                // the new data was not inserted into the hash table.
+
+                psFree(ptr->data);
+
+                ptr->data = psMemIncrRefCounter(data);
+                return data;
+            }
+            ptr = ptr->next;
+        }
+        // We did not found key in the linked list for this bucket of the hash
+        // table.  So, we insert this data at the head of that linked list.
+
+        table->buckets[hash] = hashBucketAlloc(key, data, table->buckets[hash]);
+        return data;
+    }
+}
+
+/******************************************************************************
+psHashInsert(table, key, data, itemFree): this procedure, which is part of
+the public API, inserts a new key/data pair into the hash table.
+Inputs:
+    table: a hash table
+    key: the key to use
+    data: the data to insert.
+    itemFree: a function pointer
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashAdd(psHash* table, const char *key, void *data)
+{
+    if (table == NULL) {
+        psAbort(__func__, "psHashInsert() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashInsert() called with NULL key.");
+    }
+    if (data == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL data.");
+    }
+
+    return (doHashWork(table, key, data, 0) != NULL);
+}
+
+/******************************************************************************
+psHashLookup(table, key): this procedure, which is part of the public API,
+looks up the specified key in the hash table and returns the data associated
+with that key.
+ 
+Inputs:
+    table: a hash table
+    key: the key to use
+Return:
+    The data associated with that key.
+ *****************************************************************************/
+void *psHashLookup(psHash* table,      // table to lookup key in
+                   const char *key)     // key to lookup
+{
+    if (table == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashLookup() called with NULL key.");
+    }
+
+    return doHashWork(table, key, NULL, 0);
+}
+
+/******************************************************************************
+psHashRemove(table, key, itemFree): this procedure, which is part of the
+public API, removes the specified key from the hash table.
+Inputs:
+    table: a hash table
+    key: the key to remove
+    itemFree: a function pointer
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashRemove(psHash* table, const char *key)
+{
+    void *data = NULL;
+    bool retVal = false;
+
+    if (table == NULL) {
+        psAbort(__func__, "psHashRemove() called with NULL hash table.");
+    }
+    if (key == NULL) {
+        psAbort(__func__, "psHashRemove() called with NULL key.");
+    }
+
+    data = doHashWork(table, key, NULL, 1);
+    if (data != NULL) {
+        retVal = true;
+    } else {
+        retVal = false;
+    }
+    return retVal;
+}
Index: /tags/rel2_1/psLib/src/types/psHash.h
===================================================================
--- /tags/rel2_1/psLib/src/types/psHash.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psHash.h	(revision 1553)
@@ -0,0 +1,73 @@
+
+/** @file  psHash.h
+ *  @brief Contains support for basic hashing functions.
+ *  @ingroup HashTable
+ *
+ *  This file will hold the prototypes for defining a hash table with arbitrary
+ *  data types, allocating/deallocating that has table, adding and removing
+ *  data from that hash table, and listing all keys defined in the hash table.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author George Gusciora, MHPCC
+ *   
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-09 23:40:55 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#if !defined(PS_HASH_H)
+#define PS_HASH_H
+
+/** \addtogroup HashTable
+ *  \{
+ */
+#include<stdbool.h>
+
+#include "psList.h"
+
+/** A bucket that holds an item of data. */
+typedef struct psHashBucket
+{
+    char *key;                  ///< key for this item of data
+    void *data;                 ///< the data itself
+    struct psHashBucket* next;  ///< list of other possible keys
+}
+psHashBucket;
+
+//typedef struct HashTable psHash; ///< Opaque type for a hash table
+
+/** The hash-table itself. */
+typedef struct psHash
+{
+    int nbucket;                ///< Number of buckets in hash table.
+    psHashBucket* *buckets;     ///< The bucket data.
+}
+psHash;
+
+/// Allocate hash buckets in table.
+psHash* psHashAlloc(int nbucket ///< The number of buckets to allocate.
+                   );
+
+/// Insert entry into table.
+bool psHashAdd(psHash* table,  ///< table to insert in
+               const char *key, ///< key to use
+               void *data       ///< data to insert
+              );
+
+/// Lookup key in table.
+void *psHashLookup(psHash* table,      ///< table to lookup key in
+                   const char *key      ///< key to lookup
+                  );
+
+/// Remove key from table.
+bool psHashRemove(psHash* table,       ///< table to lookup key in
+                  const char *key       ///< key to lookup
+                 );
+
+/// List all keys in table.
+psList* psHashKeyList(psHash* table    ///< table to list keys from.
+                     );
+
+/* \} */// End of DataGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/types/psList.c
===================================================================
--- /tags/rel2_1/psLib/src/types/psList.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psList.c	(revision 1553)
@@ -0,0 +1,475 @@
+
+/** @file psList.c
+ *  @brief Support for doubly linked lists
+ *  @ingroup LinkedList
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-14 01:48:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <pthread.h>                       // we need a mutex to make this stuff thread safe.
+
+#include "psError.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psList.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+
+#define ITER_INIT_HEAD ((void *)1)         // next iteration should return head
+#define ITER_INIT_TAIL ((void *)2)         // next iteration should return tail
+
+// private functions.
+static psListElem* listGetIterator(psList* list);
+static int listGetIteratorIndex(psList* list);
+static void listSetIterator(psList* list, int where, bool lockList);
+static void listFree(psList* list);
+
+psList* psListAlloc(void *data)
+{
+    psList* list = psAlloc(sizeof(psList));
+
+    p_psMemSetDeallocator(list, (psFreeFcn) listFree);
+
+    list->size = 0;
+    list->head = list->tail = NULL;
+    list->iter = ITER_INIT_HEAD;
+    list->iterIndex = PS_LIST_HEAD;
+
+    pthread_mutex_init(&(list->lock), NULL)
+    ;
+
+    if (data != NULL) {
+        psListAdd(list, data, PS_LIST_TAIL);
+    }
+
+    return list;
+}
+
+static void listFree(psList* list)
+{
+    if (list == NULL) {
+        return;
+    }
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    for (psListElem* ptr = list->head; ptr != NULL;) {
+        psListElem* next = ptr->next;
+
+        psFree(ptr->data);
+        psFree(ptr);
+
+        ptr = next;
+    }
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    pthread_mutex_destroy(&list->lock)
+    ;
+
+}
+
+bool psListAdd(psList* list, void *data, int where)
+{
+    psListElem* position;
+    psListElem* elem;
+    int cursorIndex = 0;
+
+    if (list == NULL) {
+        return false;
+    }
+
+    if (data == NULL) {
+        return false;
+    }
+
+    if (where <= PS_LIST_UNKNOWN) {
+        // / XXX What is the better way to communicate this failure to the caller?
+        psLogMsg(__func__, PS_LOG_WARN, "The given insert location (%i) for psListAdd is invalid.", where);
+        return false;
+    }
+
+    elem = psAlloc(sizeof(psListElem));
+
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    if (where > 0 && where > list->size) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Invalid index %d (only %d elements in psList); assuming tail.", where, list->size);
+        where = PS_LIST_TAIL;
+    }
+
+    if (where == PS_LIST_TAIL || list->size == 0) {
+        // insert the element at the end of the list
+        elem->prev = list->tail;
+        elem->next = NULL;
+
+        if (list->tail != NULL) {
+            list->tail->next = elem;
+        }
+
+        if (list->head == NULL) {
+            list->head = elem;
+        }
+        list->tail = elem;
+
+        list->size++;
+        list->iter = elem;
+        list->iterIndex = list->size - 1;
+    } else {
+        // move ourselves to the given position
+        listSetIterator(list, where, false);
+        position = listGetIterator(list);
+        cursorIndex = listGetIteratorIndex(list);
+
+        if (position == NULL) {
+            psError(__func__, "%s failed to move cursor to specified location (%d)", __func__, where);
+            position = list->head;         // since we no list->size != 0, this must be non-NULL
+        }
+        // insert our new element in front of the given position
+        elem->prev = position->prev;
+        elem->next = position;
+        position->prev = elem;
+
+        if (elem->prev == NULL) {          // must be front of list
+            list->head = elem;
+        } else {
+            elem->prev->next = elem;
+        }
+
+        list->size++;
+        list->iter = elem;
+        list->iterIndex = cursorIndex;
+    }
+
+    elem->data = psMemIncrRefCounter(data);
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    return true;
+}
+
+/*****************************************************************************/
+
+/*
+ * Remove an element from a list
+ */
+bool psListRemove(psList* list, void *data, int which)
+{
+    psListElem* elem = NULL;    // element to remove
+    int cursorIndex = 0;
+
+    if (list == NULL) {
+        psError(__func__, "list parameter found to be NULL in %s", __func__);
+        return false;
+    }
+    // get exclusive access to list so that other threads will not get in the way.
+    pthread_mutex_lock(&list->lock)
+    ;
+
+    if (which == PS_LIST_UNKNOWN) {
+        // search list for the data item.
+
+        int i = 0;              // index
+
+        for (psListElem* ptr = list->head; ptr != NULL; ptr = ptr->next) {
+            if (ptr->data == data) {
+                which = i;
+                break;
+            }
+            i++;
+        }
+
+        if (which == PS_LIST_UNKNOWN) {
+            psError(__func__, "Failed to find item in given psList.");
+            pthread_mutex_unlock(&list->lock)
+            ;
+            return false;
+        }
+    }
+    // position the list's cursor to the desired location
+    listSetIterator(list, which, false);
+    elem = listGetIterator(list);
+    cursorIndex = listGetIteratorIndex(list);
+
+    if (elem == NULL) {
+        psError(__func__, "Couldn't position to given index (%d) to remove element from list.", which);
+        pthread_mutex_unlock(&list->lock)
+        ;
+        return false;
+    }
+
+    list->size--;
+
+    if (elem->prev == NULL) {              // head of list?
+        list->head = elem->next;
+    } else {
+        elem->prev->next = elem->next;
+    }
+
+    if (elem->next == NULL) {              // tail of list?
+        list->tail = elem->prev;
+
+        // removed tail, so iter should be the last element of list to keep it valid
+        if (list->size > 0) {
+            list->iter = list->tail;
+            list->iterIndex = list->size - 1;
+        } else {
+            list->iter = ITER_INIT_TAIL;
+        }
+    } else {
+        elem->next->prev = elem->prev;
+        list->iter = elem->next;
+        list->iterIndex = cursorIndex;
+    }
+
+    pthread_mutex_unlock(&list->lock)
+    ;
+
+    // OK, delete list element and its data
+    psFree(elem->data);
+    psFree(elem);
+
+    return true;
+}
+
+void psListSetIterator(psList* list, int where)
+{
+    listSetIterator(list, where, true);
+}
+
+void listSetIterator(psList* list, int where, bool lockList)
+{
+    psListElem* cursor;
+    int position;
+
+    if (list == NULL) {
+        psError(__func__, "Unexpected null pointer for psList parameter (%s:%d).", __FILE__, __LINE__);
+        return;
+    }
+
+    if (where == PS_LIST_CURRENT) {
+        return;
+    }
+
+    if (lockList) {
+        pthread_mutex_lock(&list->lock)
+        ;
+        // don't want the list changing on us while we move about
+    }
+
+    if (where >= (int)list->size) {
+        list->iter = NULL;
+        if (lockList) {
+            pthread_mutex_unlock(&list->lock)
+            ;
+        }
+        return;
+    }
+
+    switch (where) {
+    case PS_LIST_HEAD:
+        list->iter = ITER_INIT_HEAD;
+        break;
+
+    case PS_LIST_TAIL:
+        list->iter = ITER_INIT_TAIL;
+        break;
+
+    case PS_LIST_PREVIOUS:
+        cursor = listGetIterator(list);
+        position = listGetIteratorIndex(list);
+
+        if (cursor != NULL) {
+            list->iter = cursor->prev;
+            list->iterIndex = position - 1;
+        }
+        break;
+
+    case PS_LIST_NEXT:
+        cursor = listGetIterator(list);
+        position = listGetIteratorIndex(list);
+
+        if (cursor != NULL) {
+            list->iter = cursor->next;
+            list->iterIndex = position + 1;
+        }
+        break;
+
+    case PS_LIST_CURRENT:
+        break;
+
+    default:
+        if (where <= PS_LIST_HEAD) {   // bascially same as PS_LIST_UNKNOWN above
+            psError(__func__, "Can't move to an unknown position.  Not moving the iterator position.");
+        } else {
+            cursor = listGetIterator(list);
+            if (cursor == NULL) {      // reset the iterator if it is invalid
+                list->iter = ITER_INIT_HEAD;
+                list->iterIndex = 0;
+            }
+
+            int position = listGetIteratorIndex(list);
+
+            if (where < position) {
+                int diff = position - where;
+
+                for (int count = 0; count < diff; count++) {
+                    listSetIterator(list, PS_LIST_PREVIOUS, false);
+                }
+            } else {
+                int diff = where - position;
+
+                for (int count = 0; count < diff; count++) {
+                    listSetIterator(list, PS_LIST_NEXT, false);
+                }
+            }
+        }
+        break;
+    }
+
+    if (lockList) {
+        pthread_mutex_unlock(&list->lock)
+        ;
+    }
+}
+
+psListElem* listGetIterator(psList* list)
+{
+    if (list == NULL) {
+        return NULL;
+    }
+
+    if (list->iter == ITER_INIT_HEAD) {
+        return list->head;
+    } else if (list->iter == ITER_INIT_TAIL) {
+        return list->tail;
+    } else {
+        return list->iter;
+    }
+}
+
+int listGetIteratorIndex(psList* list)
+{
+    if (list->iter == ITER_INIT_HEAD) {
+        return 0;
+    } else if (list->iter == ITER_INIT_TAIL) {
+        return list->size - 1;
+    } else {
+        return list->iterIndex;
+    }
+}
+
+void *psListGet(psList* list, int which)
+{
+    psListElem* element;
+
+    psListSetIterator(list, which);
+    element = listGetIterator(list);
+
+    if (element == NULL) {
+        return NULL;
+    } else {
+        return element->data;
+    }
+}
+
+/*
+ * and now return the previous/next element of the list
+ */
+void *psListGetNext(psList* list)
+{
+    return psListGet(list, PS_LIST_NEXT);
+}
+
+void *psListGetPrevious(psList* list)
+{
+    return psListGet(list, PS_LIST_PREVIOUS);
+}
+
+void *psListGetCurrent(psList* list)
+{
+    return psListGet(list, PS_LIST_CURRENT);
+}
+
+/*
+ * Convert a psList to/from a psVoidPtrArray
+ */
+psArray* psListToArray(psList* restrict list)
+{
+    psListElem* ptr;
+    unsigned int n;
+    psArray* restrict arr;
+
+    if (list == NULL) {
+        return NULL;
+    }
+
+    if (list->size > 0) {
+        arr = psArrayAlloc(list->size);
+    } else {
+        arr = psArrayAlloc(1);
+    }
+
+    arr->n = list->size;
+
+    ptr = list->head;
+    n = list->size;
+    for (int i = 0; i < n; i++) {
+        arr->data[i] = psMemIncrRefCounter(ptr->data);
+        ptr = ptr->next;
+    }
+
+    return arr;
+}
+
+psList* psArrayToList(psArray* arr)
+{
+    unsigned int n;
+    psList* list;               // list of elements
+
+    if (arr == NULL) {
+        return NULL;
+    }
+
+    list = psListAlloc(NULL);
+    n = arr->n;
+    for (int i = 0; i < n; i++) {
+        psListAdd(list, arr->data[i], PS_LIST_TAIL);
+    }
+
+    return list;
+}
+
+psList* psListSort(psList* list, psComparePtrFcn compare)
+{
+    psArray* arr;
+
+    if (list == NULL) {
+        return NULL;
+    }
+    // convert to indexable vector for use by qsort.
+    arr = psListToArray(list);
+    psFree(list);
+
+    arr = psArraySort(arr, compare);
+
+    // convert back to linked list
+    list = psArrayToList(arr);
+    psFree(arr);
+
+    return list;
+}
Index: /tags/rel2_1/psLib/src/types/psList.h
===================================================================
--- /tags/rel2_1/psLib/src/types/psList.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psList.h	(revision 1553)
@@ -0,0 +1,192 @@
+#if !defined(PS_LIST_H)
+#define PS_LIST_H
+
+/** @file psList.h
+ *  @brief Support for doubly linked lists
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @ingroup LinkedList
+ *
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-11 20:04:51 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
+#include <stdbool.h>                   // we use the bool type.
+
+#include "psCompare.h"
+#include "psArray.h"
+
+/** @addtogroup LinkedList
+ *  @{
+ */
+
+/** Special values of index into list
+ *
+ *  This list of possible list position values should be contiguous non-positive values ending with
+ *  PS_LIST_UNKNOWN.  Any value less-than-or-equal-to PS_LIST_UNKNOWN is considered a undefined position.
+ *
+ */
+enum {
+    PS_LIST_HEAD = 0,                  ///< at head
+    PS_LIST_TAIL = -1,                 ///< at tail
+    PS_LIST_PREVIOUS = -2,             ///< previous element
+    PS_LIST_CURRENT = -3,              ///< current element
+    PS_LIST_NEXT = -4,                 ///< next element
+    PS_LIST_UNKNOWN = -5               ///< unknown position (should be last in enum list)
+};
+
+/** Doubly-linked list element */
+typedef struct psListElem
+{
+    struct psListElem* prev;           ///< previous link in list
+    struct psListElem* next;           ///< next link in list
+    void *data;                        ///< real data item
+}
+psListElem;
+
+/** The psList Linked list structure.  User should not allocate this struct
+ *  directly; rather the psListAlloc should be used.
+ *
+ *  @see psListAlloc, psListFree
+ */
+typedef struct
+{
+    unsigned int size;                 ///< number of elements on list
+    psListElem* head;                  ///< first element on list (may be NULL)
+    psListElem* tail;                  ///< last element on list (may be NULL)
+    psListElem* iter;                  ///< iteration cursor
+    unsigned int iterIndex;            ///< the numeric position of the iteration cursor in the list
+    pthread_mutex_t lock;              ///< mutex to lock a node during changes
+}
+psList;
+
+/** Creates a psList linked list object.
+ *
+ *  @return psList* A new psList object.
+ */
+psList* psListAlloc(
+    void *data
+    ///< initial data item; may be NULL if no an empty psList is desired
+)
+;
+
+/** Adds an element to a psList at position given.
+ *
+ *  @return psList* The psList with added data item.  If list parameter is
+ *                      NULL, the return value will also be NULL.
+ */
+bool psListAdd(
+    psList* restrict list,             ///< list to add to (if NULL, nothing is done)
+    void *data,                        ///< data item to add.  If NULL, list is not modified.
+    int where                          ///< index, PS_LIST_HEAD, PS_LIST_TAIL, or numbered location.
+);
+
+/** Remove an item from a list.  If which parameter is PS_LIST_UNKNOWN,
+ *
+ *  @return bool        TRUE if element is successfully removed, otherwise FALSE.
+ */
+bool psListRemove(
+    psList* restrict list,
+    ///< list to remove element from
+    void *data,
+    ///< if which is PS_LIST_UNKNOWN, data item to find and remove, otherwise this is ignored.
+    int which
+    ///< index of item, or PS_LIST_UNKNOWN, PS_LIST_NEXT, PS_LIST_PREV, or numbered location.
+);
+
+/** Retrieve an item from a list.
+ *
+ *  @return void*       the item corresponding to the which parameter.  If
+ *                      which is invalid (e.g., a numbered index greater
+ *                      than the list size or if the list is empty), a
+ *                      NULL is returned.
+ */
+void *psListGet(
+    psList* restrict list,             ///< list to retrieve element from
+    int which                          ///< index number, or PS_LIST_NEXT, PS_LIST_PREV, PS_LIST_UNKNOWN
+);
+
+/** Set the iterator of the list to a given position.  If where is invalid the
+ *  iterator position is not changed.
+ *
+ */
+void psListSetIterator(
+    psList* restrict list,             ///< list to retrieve element from
+    int where                          ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Get next element relative to the iterator.  This also moves the iterator to
+ *  the next list position.
+ *
+ *  @return void*       the data item next on the list or NULL if the iterator
+ *                      is already pointing to the last element or the list
+ *                      parameter was NULL.
+ */
+void *psListGetNext(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Get current element according to the psList's iterator cursor.  This does
+ *  not move the iterator location.
+ *
+ *  @return void*       the data item cooresponding to current iterator
+ *                      cursor position of the list, or NULL if either the
+ *                      iterator is not valid or list parameter was NULL.
+ */
+void *psListGetCurrent(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Get previous element relative to list's iterator. This also moves the
+ *  iterator to the previous list position.
+ *
+ *  @return void*       the data item previous on the list or NULL if the iterator
+ *                      is already pointing to the first element or the list
+ *                      parameter was NULL.
+ */
+void *psListGetPrevious(
+    psList* restrict list              ///< list to retrieve element from
+);
+
+/** Convert a linked list to an array
+ *
+ *  @return psArray* A new psArray populated with elements from the list,
+ *                      or NULL if the given dlist parameter is NULL.
+ */
+psArray* psListToArray(
+    psList* dlist                      ///< List to convert
+);
+
+/** Convert array to a doubly-linked list
+ *
+ *  @return psList* A new psList populated with elements formt the psArray,
+ *                      or NULL is the given arr parameter is NULL.
+ */
+psList* psArrayToList(
+    psArray* arr                       ///< vector to convert
+);
+
+/** Sort a list via a comparison function.
+ *
+ *  The comparison function must return an integer less than, equal to, or 
+ *  greater than zero if the first argument is considered to be respectively 
+ *  less than, equal to, or greater than the second. 
+ *
+ *  If two members compare as equal, their order in the sorted array is 
+ *  undefined.
+ *
+ *  @return psList*     Sorted list.
+ */
+psList* psListSort(
+    psList* list,                      ///< the list to sort
+    psComparePtrFcn compare            ///< the comparison function
+);
+
+/// @} End of DataGroup Functions
+
+#endif
Index: /tags/rel2_1/psLib/src/types/psMetadata.c
===================================================================
--- /tags/rel2_1/psLib/src/types/psMetadata.c	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psMetadata.c	(revision 1553)
@@ -0,0 +1,761 @@
+
+/** @file  psMetadata.c
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-14 02:55:46 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include<stdio.h>
+#include<stdarg.h>
+#include<string.h>
+
+#include "fitsio.h"
+#include "psType.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psList.h"
+#include "psHash.h"
+#include "psMetadata.h"
+#include "psString.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+#define FITS_ERROR(STRING,PS_ERROR)                  \
+fits_get_errstatus(status, fitsErr);             \
+psError( __func__, STRING, PS_ERROR, fitsErr);   \
+status = 0;                                      \
+return output;
+
+/** Maximum size of a FITS line */
+#define FITS_LINE_SIZE 80
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH 1024
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+static int metadataId = 0;
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static void metadataItemFree(psMetadataItem* metadataItem)
+{
+    psMetadataType type;
+
+    type = metadataItem->type;
+
+    if (metadataItem == NULL) {
+        return;
+    }
+
+    psFree(metadataItem->name);
+    psFree(metadataItem->comment);
+    psFree(metadataItem->items);
+
+    if (type == PS_META_STR ||
+            type == PS_META_IMG ||
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+        psFree(metadataItem->data.V);
+    }
+}
+
+static void metadataFree(psMetadata* metadata)
+{
+    if (metadata == NULL) {
+        return;
+    }
+    psFree(metadata->list);
+    psFree(metadata->table);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+psMetadataItem* psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    // Get the variable list parameters to pass to allocation function
+    va_start(argPtr, comment);
+
+    // Call metadata item allocation
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    return metadataItem;
+}
+
+psMetadataItem* psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment,
+                                     va_list argPtr)
+{
+    psMetadataItem* metadataItem = NULL;
+
+    if (name == NULL) {
+        psError(__func__, "Null value for name not allowed");
+        return NULL;
+    }
+    // Allocate metadata item
+    metadataItem = (psMetadataItem* ) psAlloc(sizeof(psMetadataItem));
+    if (metadataItem == NULL) {
+        psAbort(__func__, "Failed to allocate memory");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
+
+    // Allocate and set metadata item comment
+    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    if (comment == NULL) {
+        // Per SDRS, null isn't allowed, must use "" instead
+        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
+    } else {
+        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
+    }
+
+    // Set metadata item unique id
+    *(int *)(&metadataItem->id) = ++metadataId;
+
+    // Set metadata item type
+    metadataItem->type = type;
+
+    // Set metadata item value
+    switch (type) {
+    case PS_META_ITEM_SET:
+        metadataItem->data.V = NULL;
+        break;
+    case PS_META_BOOL:
+        metadataItem->data.B = (bool)va_arg(argPtr, int);
+        break;
+    case PS_META_S32:
+        metadataItem->data.S32 = va_arg(argPtr, psS32);
+        break;
+    case PS_META_F32:
+        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
+        break;
+    case PS_META_F64:
+        metadataItem->data.F64 = va_arg(argPtr, psF64);
+        break;
+    case PS_META_STR:
+        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, "Invalid psMetadataType: %d", type);
+    }
+
+    // Allocate and set metadata item name
+    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    vsprintf(metadataItem->name, name, argPtr);
+
+    // Allocate metadata items with same name.
+    metadataItem->items = psListAlloc(NULL);
+
+    return metadataItem;
+}
+
+psMetadata* psMetadataAlloc(void)
+{
+    psList* list = NULL;
+    psHash* table = NULL;
+    psMetadata* metadata = NULL;
+
+    // Allocate metadata
+    metadata = (psMetadata* ) psAlloc(sizeof(psMetadata));
+    if (metadata == NULL) {
+        psAbort(__func__, "Failed to allocate metadata");
+    }
+    // Set deallocator
+    p_psMemSetDeallocator(metadata, (psFreeFcn) metadataFree);
+
+    // Allocate metadata's internal containers
+    list = (psList* ) psListAlloc(NULL);
+    if (list == NULL) {
+        psAbort(__func__, "Failed to allocate list");
+    }
+
+    table = (psHash* ) psHashAlloc(10);
+    if (table == NULL) {
+        psAbort(__func__, "Failed to allocate table");
+    }
+
+    metadata->list = list;
+    metadata->table = table;
+
+    return metadata;
+}
+
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
+    psHash *mdTable = NULL;
+    psList *mdList = NULL;
+    psMetadataItem *existingEntry = NULL;
+    psMetadataItem *newFolderEntry = NULL;
+    psMetadataType newType = PS_META_ITEM_SET;
+
+    if(md == NULL) {
+        psError( __func__, "Null metadata collection not allowed" );
+        return false;
+    }
+
+    if(metadataItem == NULL) {
+        psError( __func__, "Null metadata item not allowed" );
+        return false;
+    }
+
+    newType = metadataItem->type;
+
+    mdTable = md->table;
+    if(mdTable == NULL) {
+        psError( __func__, "Null metadata table not allowed" );
+        return false;
+    }
+
+    mdList = md->list;
+    if(mdList == NULL) {
+        psError( __func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    key = metadataItem->name;
+    if(key == NULL) {
+        psError(__func__, "Null key item not allowed");
+        return false;
+    }
+
+    // See if key is already in table
+    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+    if(existingEntry != NULL) {
+
+        if(existingEntry->type == PS_META_ITEM_SET) {
+
+            // Add leaf node to existing folder node
+            if(!psListAdd(existingEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                         metadataItem->name );
+                return false;
+            }
+        } else if(existingEntry->type != PS_META_ITEM_SET && newType!= PS_META_ITEM_SET) {
+
+            // Leaf node replaces another leaf. Make new folder node and add leaves.
+            newFolderEntry = psMetadataItemAlloc(key, PS_META_ITEM_SET, NULL, NULL);
+
+            if(!psListAdd(newFolderEntry->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psListAdd(newFolderEntry->items, metadataItem, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, newFolderEntry)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                psFree(newFolderEntry);
+                return false;
+            }
+
+            // Remove local reference to new folder node
+            psMemDecrRefCounter(newFolderEntry);
+        } else {
+
+            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
+            if(!psListAdd(metadataItem->items, existingEntry, PS_LIST_TAIL)) {
+                psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashRemove(mdTable, key)) {
+                psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
+                return false;
+            }
+
+            if(!psHashAdd(mdTable, key, metadataItem)) {
+                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+                return false;
+            }
+        }
+    } else {
+
+        // Node doesn't exist - Add new metadata item to metadata collection's hash
+        if(!psHashAdd(mdTable, key, metadataItem)) {
+            psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
+            return false;
+        }
+    }
+
+    // Add all items to metadata collection's list, even if they have the same metadata item names
+    if(!psListAdd( mdList, metadataItem, where )) {
+        psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                 metadataItem->name );
+        return false;
+    }
+
+    return true;
+}
+
+bool psMetadataAdd(psMetadata* restrict md, int where, const char *name, psMetadataType type,
+                   const char *comment, ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    va_start(argPtr, comment);
+    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
+    va_end(argPtr);
+
+    if (!psMetadataAddItem(md, where, metadataItem)) {
+        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                metadataItem->name);
+        psFree(metadataItem);
+        return false;
+    }
+    // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
+    // here
+    psMemDecrRefCounter(metadataItem);
+
+    return true;
+}
+
+
+
+bool psMetadataRemove(psMetadata* restrict md, int where, const char *restrict key)
+{
+    int numChildren = 0;
+    psList* mdList = NULL;
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+    psMetadataItem* entryChild = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return false;
+    }
+    // Select removal by key or index
+    if (key != NULL) {
+
+        // Remove by key name
+        entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item. Name: %s", key);
+            return false;
+        }
+
+        numChildren = entry->items->size;
+        if (entry->type == PS_META_ITEM_SET && numChildren > 0) {
+
+            // Table entry has children. Entry and children must be removed from metadata collection's list
+            psListSetIterator(entry->items, PS_LIST_HEAD);
+            entryChild = psListGetCurrent(entry->items);
+            while (entryChild != NULL) {
+                if (!psListRemove(mdList, entryChild, PS_LIST_UNKNOWN)) {
+                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                    return false;
+                }
+                entryChild = psListGetNext(entry->items);
+            }
+        } else {
+
+            // Table entry has no children. Remove entry from metadata collection's list
+            if (!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
+                psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+                return false;
+            }
+        }
+        // Remove entry from metadata collection's table
+        if (!psHashRemove(mdTable, key)) {
+            psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
+            return false;
+        }
+    } else {
+
+        // Remove by index
+        entry = psListGet(mdList, where);
+        if (entry == NULL) {
+            psError(__func__, "Couldn't find metadata item in list. Index: %d", where);
+            return false;
+        }
+
+        key = entry->name;
+        if (key == NULL) {
+            psError(__func__, "Null key name not allowed. Index: %d", where);
+            return false;
+        }
+        // Use recursive remove, now that key is known
+        psMetadataRemove(md, PS_LIST_UNKNOWN, key);
+    }
+
+    return true;
+}
+
+psMetadataItem* psMetadataLookup(psMetadata* restrict md, const char *restrict key)
+{
+    psHash* mdTable = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdTable = md->table;
+    if (mdTable == NULL) {
+        psError(__func__, "Null metadata table not allowed");
+        return NULL;
+    }
+
+    if (key == NULL) {
+        psError(__func__, "Null key name not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psHashLookup(mdTable, key);
+    if (entry == NULL) {
+        psError(__func__, "Could not find metadata item. Key: %s", key);
+        return NULL;
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGet(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    entry = (psMetadataItem* ) psListGet(mdList, where);
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item with given index. Index: %d", where);
+        return NULL;
+    }
+
+    return entry;
+}
+
+bool psMetadataSetIterator(psMetadata* restrict md, int where)
+{
+    psList* mdList = NULL;
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return false;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return false;
+    }
+
+    psListSetIterator(mdList, where);
+
+    return true;
+}
+
+psMetadataItem* psMetadataGetNext(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetNext(mdList);
+        } else {
+            return psListGetNext(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item");
+    }
+
+    return entry;
+}
+
+psMetadataItem* psMetadataGetPrevious(psMetadata* restrict md, const char *restrict match, int which)
+{
+    psList* mdList = NULL;
+    psMetadataItem* entry = NULL;
+
+
+    if (md == NULL) {
+        psError(__func__, "Null metadata collection not allowed");
+        return NULL;
+    }
+
+    mdList = md->list;
+    if (mdList == NULL) {
+        psError(__func__, "Null metadata list not allowed");
+        return NULL;
+    }
+
+    psListSetIterator(mdList, which);
+    entry = psListGetCurrent(mdList);
+    while (entry != NULL) {
+        if(match != NULL) {
+            if (!strncmp(match, entry->name, strlen(match))) {
+
+                // Match found
+                return entry;
+            }
+            entry = psListGetPrevious(mdList);
+        } else {
+            return psListGetPrevious(mdList);
+        }
+    }
+
+    // Match not found
+    if (entry == NULL) {
+        psError(__func__, "Couldn't find metadata item", match);
+    }
+
+    return entry;
+}
+
+void psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* restrict metadataItem)
+{
+    psMetadataType type;
+
+    if (fd == NULL) {
+        psError(__func__, "Null file descriptor not allowed");
+        return;
+    }
+
+    if (format == NULL) {
+        psError(__func__, "Null format not allowed");
+        return;
+    }
+
+    if (metadataItem == NULL) {
+        psError(__func__, "Null metadata not allowed");
+        return;
+    }
+
+    type = metadataItem->type;
+
+    switch (type) {
+    case PS_META_BOOL:
+        fprintf(fd, format, metadataItem->data.B);
+        break;
+    case PS_META_S32:
+        fprintf(fd,format, metadataItem->data.S32);
+        break;
+    case PS_META_F32:
+        fprintf(fd, format, metadataItem->data.F32);
+        break;
+    case PS_META_F64:
+        fprintf(fd, format, metadataItem->data.F64);
+        break;
+    case PS_META_STR:
+        fprintf(fd, format, metadataItem->data.V);
+        break;
+    case PS_META_ITEM_SET:
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+    default:
+        psError(__func__, " Invalid psMetadataType to print: %d", type);
+    }
+}
+
+psMetadata* psMetadataFReadHeader(psMetadata* output, char *extName, int extNum, fitsfile * fd)
+{
+    bool tempBool;
+    bool success;
+    char keyType;
+    char keyName[FITS_LINE_SIZE];
+    char keyValue[FITS_LINE_SIZE];
+    char keyComment[FITS_LINE_SIZE];
+    char fitsErr[MAX_STRING_LENGTH];
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    int keyNum = 0;
+    psMetadataType metadataItemType;
+
+    if (fd == NULL) {
+        psError(__func__, "Null FITS file descriptor not allowed");
+        return NULL;
+    }
+
+    if (extName == NULL && extNum == 0) {
+        psError(__func__, "Null extName and extNum = 0 not allowed");
+        return NULL;
+    } else if (extName && extNum) {
+        psError(__func__, "Both extName and extNum arguments should not have non zero values.");
+        return NULL;
+    }
+    // Allocate metadata if user didn't
+    if (output == NULL) {
+        output = psMetadataAlloc();
+    }
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if (extName != NULL) {
+        if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %s: %s", extName);
+        }
+    } else {
+        if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {
+            FITS_ERROR("FITS error while locating header %d: %s", extNum);
+        }
+    }
+
+    // Get number of key names
+    if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
+        FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+    }
+    // Get each key name. Keywords start at one.
+    for (i = 1; i <= numKeys; i++) {
+        if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
+            FITS_ERROR("FITS error while reading key %d: %s", keyNum);
+        }
+        if (fits_get_keytype(keyValue, &keyType, &status) != 0) {
+            fits_get_errstatus(status, fitsErr);
+            if (status != VALUE_UNDEFINED) {
+                FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
+            } else {
+                // Some keywords are still valid even though they don't have a type, like COMMENTS and
+                // HISTORY
+                keyType = 'C';
+                status = 0;
+            }
+        }
+
+        switch (keyType) {
+        case 'I':
+            metadataItemType = PS_META_S32;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atoi(keyValue));
+            break;
+        case 'F':
+            metadataItemType = PS_META_F64;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
+                              atof(keyValue));
+            break;
+        case 'C':
+            metadataItemType = PS_META_STR;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, keyValue);
+            break;
+        case 'L':
+            metadataItemType = PS_META_BOOL;
+            tempBool = (keyValue[0] == 'T') ? 1 : 0;
+            success =
+                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment, tempBool);
+            break;
+        case 'U':
+        case 'X':
+        default:
+            psError(__func__, "Invalid psMetadataType: %c", keyType);
+            return output;
+        }
+
+        if (!success) {
+            psError(__func__, "Failed to add metadata item. Name: %s", keyName);
+            return output;
+        }
+    }
+
+    return output;
+}
Index: /tags/rel2_1/psLib/src/types/psMetadata.h
===================================================================
--- /tags/rel2_1/psLib/src/types/psMetadata.h	(revision 1553)
+++ /tags/rel2_1/psLib/src/types/psMetadata.h	(revision 1553)
@@ -0,0 +1,298 @@
+
+/** @file  psMetadata.h
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 01:23:20 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#ifndef PS_METADATA_H
+#define PS_METADATA_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <fitsio.h>
+
+#include "psHash.h"
+#include "psList.h"
+
+/// @addtogroup Metadata
+/// @{
+
+/** Metadata item type.
+ *
+ * Enumeration for maintaining metadata item types.
+ */
+typedef enum {
+    PS_META_ITEM_SET = 0,              ///< Null. Metadata is in psMetadataItem.items
+    PS_META_BOOL,                      ///< Boolean data.
+    PS_META_S32,                       ///< Signed 32-bit integer data.
+    PS_META_F32,                       ///< Single-precision float data.
+    PS_META_F64,                       ///< Double-precision float data.
+    PS_META_STR,                       ///< String data (Stored in as void *).
+    PS_META_IMG,                       ///< Image data (Stored in as void *).
+    PS_META_JPEG,                      ///< JPEG data (Stored in as void *).
+    PS_META_PNG,                       ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                   ///< Other data (Stored in as void *).
+    PS_META_NTYPE                      ///< Number of types. Must be last.
+} psMetadataType;
+
+/** Metadata item data structure.
+ *
+ * Struct for maintaining metadata items of varying types. It also contains
+ * information about the item name, flags, comments, and other items with the same name.
+ */
+typedef struct psMetadataItem
+{
+    const int id;                      ///< Unique ID for metadata item.
+    char *restrict name;               ///< Name of metadata item.
+    psMetadataType type;               ///< Type of metadata item.
+    union {
+        bool B;                        ///< boolean data
+        psS32 S32;                     ///< Signed 32-bit integer data.
+        psF32 F32;                     ///< Single-precision float data.
+        psF64 F64;                     ///< Double-precision float data.
+        psPTR V;                       ///< Pointer to other type of data.
+    } data;                            ///< Union for data types.
+    char *comment;                     ///< Optional comment ("", not NULL).
+    psList* restrict items;            ///< List of psMetadataItems with same name.
+}
+psMetadataItem;
+
+/** Metadata data structure.
+ *
+ *  Struct for holding metadata items. Metadata items are held in two 
+ *  containers. The first employs a doubly-linked list to preserve the order 
+ *  of the metadata. The second container employs a hash table which
+ *  allows fast lookup when given a metadata keyword.
+ */
+typedef struct psMetadata
+{
+    psList* restrict list;             ///< the metadata in linked-list
+    psHash* restrict table;            ///< the metadata in a hash table
+}
+psMetadata;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Create a metadata item.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and 
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAlloc(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata item with va_list.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata 
+ *  struct. The name argument specifies the name to use for this item, and
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the 
+ *  appropriate type and flag. The comment argument is a fixed string used to 
+ *  comment the metadata item. The arguments to the name formatting codes and 
+ *  the metadata itself are passed as arguments following the comment string. 
+ *  The data must be a pointer for any of the elements stored in data.void. 
+ *  The argument list must be interpreted appropriately by the va_list 
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocV(
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+
+/** Create a metadata collection.
+ *
+ *  Returns an empty metadata container with fully allocated internal metadata 
+ *  containers.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataAlloc(void);
+
+/** Add existing metadata item to metadata collection.
+ *
+ *  Add a metadata item that has already been created to the metadata 
+ *  collection.
+ *
+ *  @return bool: True for success, false for failure.
+ */
+bool psMetadataAddItem(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    psMetadataItem* restrict item      ///< Metadata item to be added.
+);
+
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataAdd(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    psMetadataType type,               ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Remove an item from metadata collection.
+ *
+ *  Items may be removed from metadata by specifing a key or location. If the 
+ *  name is null, the where argument is used instead. If name is not null, 
+ *  where is set to PS_LIST_UNKNOWN. If the item is found, it is removed from 
+ *  the metadata and true is returned.  If the key is not unique, then all 
+ *  items corresponding to it are removed.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataRemove(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where,                         ///< Location to be removed.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on key name.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is 
+ *  non-unique, the first item is returned. If the item is not found, null is 
+ *  returned.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataLookup(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadata item.
+    const char *restrict key           ///< Name of metadata key.
+);
+
+/** Find an item in the metadata collection based on list index.
+ *
+ *  Items may be found in the metadata by their entry position in the list 
+ *  container.
+ *
+ *  @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGet(
+    psMetadata* restrict md,           ///< Metadata collection to insert metadat item.
+    int where                          ///< Location to be retrieved.
+);
+
+/** Set or reset metadata iterator.
+ *
+ *  Metadata may be iterated by setting or resetting an iterator to a location 
+ *  in the metadata list.
+ *
+ * @return void: void.
+ */
+bool psMetadataSetIterator(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    int where                          ///< Location of iterator.
+);
+
+/** Get next metadata item.
+ *
+ * Get next metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetNext(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Get previous metadata item.
+ *
+ * Get previous metadata item in iterator list.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGetPrevious(
+    psMetadata* restrict md,           ///< Metadata collection to iterate.
+    const char *restrict match,        ///< Beginning of key name.
+    int which                          ///< Iterator to be used.
+);
+
+/** Print metadata item to file.
+ *
+ *  Metadata items may be printed to an open file descriptor based on a 
+ *  provided format. The format is a sprintf format statement with exactly 
+ *  one % formatting command. If the metadata item type is a numeric type, 
+ *  this formatting command must also be numeric, and the type conversion 
+ *  performed to the value to match the format type. If the metadata type is 
+ *  a string, the fromatting command must also be for a string. If the
+ *  metadata type is any other data type, printing is not allowed.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+void psMetadataItemPrint(
+    FILE * fd,                         ///< Pointer to file to write metadata item.
+    const char *format,                ///< Format to print metadata item.
+    const psMetadataItem* restrict metadataItem ///< Metadata item to print.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported. This file is currently unimplemented.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extname,                     ///< File name extension string.
+    int extnum,                        ///< File name extension number. Starts at 1.
+    char *filename                     ///< Name of file to read.
+);
+
+/** Read metadata header.
+ *
+ *  Read a metadata header from file. If the file is not found, an error is 
+ *  reported.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+psMetadata* psMetadataFReadHeader(
+    psMetadata* output,                ///< Resulting metadata from read.
+    char *extName,                     ///< File name extension string.
+    int extNum,                        ///< File name extension number.
+    fitsfile * fd                      ///< Pointer to file to read.
+);
+
+/// @}
+
+#endif
Index: /tags/rel2_1/psLib/test/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/.cvsignore	(revision 1553)
@@ -0,0 +1,3 @@
+temp
+tst_psTime_01
+tst_psTime_02
Index: /tags/rel2_1/psLib/test/FullUnitTest
===================================================================
--- /tags/rel2_1/psLib/test/FullUnitTest	(revision 1553)
+++ /tags/rel2_1/psLib/test/FullUnitTest	(revision 1553)
@@ -0,0 +1,710 @@
+#!/usr/bin/perl
+#
+#  This is a perl script test harness which will recursively search the
+#  directory tree looking for files named UnitTest and then execute
+#  the script
+#
+#  SYNOSIS :  FullUnitTest options arguements
+#
+#       where  options =
+#             --verbose     Display extra information to user
+#             --noverbose   Don't display extra information to user
+#             --recursiv e  Recursively run tests in directory tree
+#             --norecursive Test only the specified or current directory
+#             --silent      Don't display any information to user
+#             --nosilent    Display progress of script to user
+#
+#              arguements = directory(ies) to perform tests
+#
+#  RETURN : integer number of tests which failed
+#
+#  $Revision: 1.13 $  $Name: not supported by cvs2svn $
+#  $Date: 2004-08-14 02:27:02 $
+#
+#  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+#
+##############################################################################
+
+# Provide functions for determining the pathname of current working directory
+use Cwd;
+
+# Provides functions for handling long command line options
+use Getopt::Long;
+
+# Assign variables based on the presence of command line options to the script
+# The ! option allows for --nooption to be set to zero
+# (e.g. --noverbose --recursive causes $verbose=0 and $recursive=1)
+GetOptions(
+    "verbose!"   => \$verbose,
+    "recursive!" => \$recursive,
+    "silent!"    => \$silent,
+    "clean!"     => \$clean
+);
+
+# Check if both silent and verbose options are set and if so stop the script
+die "Can't specify both verbose and silent options." if ( $verbose && $silent );
+
+# Set up the PSLIB_ROOT environment variable if the user doesn't have
+if ( !$ENV{'PSLIB_ROOT'} ) {
+
+    # Use the directory directly above where FullUnitTest script resides
+    $PSLIB_ROOT = `cd ..;pwd`;
+
+    # Remove newline for the end of path returned
+    chomp($PSLIB_ROOT);
+
+    # Set the environment variable
+    $ENV{'PSLIB_ROOT'} = $PSLIB_ROOT;
+    print("PSLIB_ROOT not found: set to $PSLIB_ROOT.\n") if $verbose;
+}
+
+# add PSLIB_ROOT/lib to LD_LIBRARY_PATH and DYLD_LIBRARY_PATH environment
+# variables
+$ENV{'LD_LIBRARY_PATH'}   = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'LD_LIBRARY_PATH'}";
+$ENV{'DYLD_LIBRARY_PATH'} = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'DYLD_LIBRARY_PATH'}";
+
+# Initialize variables for counting the makes and test failures and the
+# total makes and tests performed
+$makeFailCount       = 0;
+$testpointFailCount  = 0;
+$testDriverFailCount = 0;
+$totalTestpoints     = 0;
+$totalTestDrivers    = 0;
+$totalMakes          = 0;
+
+# Initialize variable indicating how many arguements were passed
+$args = 0;
+
+# Loop through all the arguements passed to the script
+foreach (@ARGV) {
+
+    # Remove newline if there is one
+    chomp;
+
+    # Increment number of arguements found
+    $args++;
+
+    # Set variable to current working directory
+    $cwd = cwd;
+
+    # Change directory to the directory of the arguement
+    chdir($_);
+
+    # Check for the recursive option
+    if ($recursive) {
+
+        # Invoke subroutine to go to the lowest directory in tree
+        # starting at the specified directory
+        &worm($_);
+    }
+    else {
+
+        # Invoke subroutines to run the test at the specified directory
+        &makeTestDrivers($_);
+        &executeTestDrivers($_);
+    }
+
+    # Change directory back to the directory where FullUnitTest was invoked
+    chdir($cwd);
+}
+
+# Check if there were no arguements specified
+if ( $args == 0 ) {
+
+    # Display message to user that all directories under the current will be
+    # tested
+    print("Recursively testing current directory tree.\n") if $verbose;
+
+    # Invoke subroutine to go to recursively test each directory in tree
+    &worm( $ENV{"PWD"} );
+}
+
+# Check if there were any failures during make or testing
+if ( $makeFailCount > 0 || $testDriverFailCount > 0 ) {
+
+    # Display summary of failures
+    print("\nMake Failures = $makeFailCount out of $totalMakes");
+    print(
+"\nTest Driver Failures = $testDriverFailCount out of $totalTestDrivers\n"
+    );
+    print( "\nMakes that failed:\n  " . join( "\n  ", @makesFailed ) . "\n" )
+      if $makeFailCount;
+    print( "\nTests that failed:\n  " . join( "\n  ", @testsFailed ) . "\n" )
+      if $testDriverFailCount;
+}
+else {
+
+    # Display message of all makes and tests pass to user if silent option
+    # not specified
+    print(
+"\nAll $totalTestDrivers Test Drivers Passed with $totalTestpoints Testpoints.\n"
+      )
+      if ( !$silent );
+}
+
+# Exit with the number of tests that failed
+exit($testDriverFailCount);
+
+################################################################################
+#
+# SUBROUTINE: worm
+#
+#     Description:  This subroutine will perform the necessary unit tests be
+#                   calling makeTestDrivers and executeTestDrivers  subroutines
+#                   and then check each subdirectory below the base directory
+#                   recursively.
+#
+#     Parameter(s):  base directory to start testing
+#
+#     Return:  None
+#
+################################################################################
+
+sub worm {
+
+    # Assign local variable to input parameter
+    local ($base_dir) = @_;
+    local ( @files, $i );
+
+    # Invoke subroutine to make test driver in the base directory
+    &makeTestDrivers($base_dir);
+
+    # Invoke subroutine to execute tests in the base directory
+    &executeTestDrivers($base_dir);
+
+    # Create array of entries found in directory
+    @files = <*>;
+
+    # Loop through the file list looking for another directory that is not
+    # labelled CVS and recursively invoke subroutine worm
+    $i = 0;
+    while ( $files[$i] ) {
+
+        # Check for directory and directory not labelled CVS
+        if (   -d $files[$i]
+            && ( $files[$i] ne "CVS" )
+            && ( $files[$i] ne "temp" )
+            && ( $files[$i] ne "verified" ) )
+        {
+
+            # Change current directory to directory found
+            chdir( $files[$i] );
+
+            # Invoke subroutine worm again
+            &worm( $files[$i] );
+
+            # Change current directory back to parent
+            chdir("..");
+        }
+
+        # Increment file list index
+        $i++;
+    }
+}
+
+################################################################################
+#
+#  SUBROUTINE: makeTestDrivers
+#
+#      Description:  This subroutine will perform a make for all the necessary
+#                    test drivers.    This will occur in the specified
+#                    base directory which is passed as the only parameter.
+#
+#      Parameter(s):  base directory where make and test drivers are located
+#
+#      Return:  None
+#
+################################################################################
+
+sub makeTestDrivers {
+    local ($base_dir) = @_;
+    local ($pwd);
+
+    # Set variable pwd to current working directory
+    $pwd = cwd;
+
+    # Display message to user in which directory testing is taken place only
+    # if the silent command option was not specified
+    print("---- Entering $pwd ----\n") if ( !$silent );
+
+    # Check for the existence of a file name Makefile in current directory
+    if ( -e "Makefile" ) {
+
+        # Increment the total number of makes executed
+        $totalMakes++;
+
+        if ($clean) {
+
+            # Execute the make clean
+            `make clean`;
+
+            # Execute the make distclean
+            `make distclean`;
+        }
+
+        # Execute the make and save results
+        $_ = join( "\n|| ", split( "\n", "\n" . `make` ) );
+
+        # Check the output of make for return value != 0 or any of the
+        # following words: FAILED, FAULT, ERROR, Not found, SIGNAL
+        if (   ( $? != 0 )
+            || m/FAILED/i
+            || m/FAULT/i
+            || m/\bERROR/i
+            || m/Not found/i
+            || m/SIGNAL/i )
+        {
+
+            # Display the errored output of make if silent option not enabled
+            print("$_\n") if ( !$silent );
+
+            # Display the make failed in the current directory
+            print("\nMake for $pwd Failed\n");
+
+            # Increment the number of makes that have failed
+            $makeFailCount++;
+
+            # Push the current working directory onto the list of failed
+            # make directories list
+            push( @makesFailed, $pwd );
+        }
+        else {
+
+            # Display the results of the successful make if verbose option set
+            print("$_\n") if $verbose;
+
+            # Display the make was successful if silent option not set
+            print("\nMake successful.\n") if ( !$silent );
+            if ($clean) {
+                `make install`;
+            }
+        }
+    }
+}
+
+################################################################################
+#
+#  SUBROUTINE: executeTestDrivers
+#
+#      Description:  This subroutine will execute all the necessary
+#                    test drivers.    This will occur in the specified
+#                    base directory which is passed as the only parameter.
+#
+#      Parameter(s):  base directory where make and test drivers are located
+#
+################################################################################
+
+sub executeTestDrivers {
+    local ($base_dir) = @_;
+    local ( @files, $j );
+    local ($pwd);
+    local ($exitValue) = 0;
+
+    # Set variable to pwd to current test directory
+    $pwd = cwd;
+
+    # Create a list of all elements in base directory
+    @files = <*>;
+
+    # Loop through all the items in the files array
+    $initialTest = 0;
+    $j           = 0;
+    while ( $files[$j] ) {
+
+        # Check that the item is not a directory and is executable and
+        # conforms to the test driver naming convention TST
+        if (   !( -d $files[$j] )
+            && ( -x $files[$j] )
+            && ( $files[$j] =~ /^TST/i || $files[$j] =~ /^ATST/i ) )
+        {
+
+            # Increment total number of test drivers executed
+            $totalTestDrivers++;
+
+            # Perform subdirectory checks only the first time a test
+            # file is found with the list of enteries
+            if ( $initialTest == 0 ) {
+                $initialTest++;
+
+                # Check for a temp subdirectory already exists and if not
+                # then create one
+                &checkForTempDirectory();
+
+                # Check for the presence of verified directory
+                if ( &checkForVerifiedDirectory() ) {
+
+    # Display message to user that verified directories do not
+    # exist eventhough TST files have been found
+    #                    print("Unable to execute test drivers in $base_dir\n");
+                    print("No verified subdirectory present.\n") if ($verbose);
+
+               # Increment test fail count
+               #                   $testDriverFailCount++;
+               # Save the file failed
+               #                    push(@testsFailed, $pwd . "/" . $files[$j]);
+               #                    return;
+                }
+            }
+
+            # Display message to user of which test driver is being executed
+            print("--- Executing test driver $files[$j]\n") if ( !$silent );
+
+            # Execute the test driver
+            system(
+"./$files[$j] 1> temp/$files[$j].stdout 2> temp/$files[$j].stderr"
+            );
+            $retVal = $?;
+
+            # Count testpoints
+            $testPattern = "\"\\*\\*\\*\\* TESTPOINT \\*\\*\\*\\*\"";
+            $totalPoints = `grep -c $testPattern temp/$files[$j].stdout`;
+            $totalPoints += `grep -c $testPattern temp/$files[$j].stderr`;
+            $failPoints =
+              `grep "> TESTPOINT FAILED" temp/$files[$j].stdout | wc -l`;
+            $failPoints +=
+              `grep "> TESTPOINT FAILED" temp/$files[$j].stderr | wc -l`;
+            $testpointFailCount += $failPoints;
+            $totalTestpoints    += $totalPoints;
+
+            # Check result of test driver
+            if (   ( ( $retVal != 0 ) && ( $files[$j] =~ /^TST/i ) )
+                || ( ( $retVal == 0 ) && ( $files[$j] =~ /^ATST/i ) ) )
+            {
+
+                # Display test driver failed
+                $failPoints++;
+                print(
+                    "Test driver: $files[$j] Failed (Return value $retVal).\n");
+
+                # Increment the total number of test failed
+                $testDriverFailCount++;
+
+                # Push the current working directory on the list of failed
+                push( @testsFailed, $pwd . "/" . $files[$j] );
+            }
+            else {
+
+               # Create filter versions of STDOUT and STDERR to replace variable
+               # items such as date, time and host
+                &filterStdFiles( $files[$j] );
+
+                # Perform difference on STDOUT file collected
+                # with verified files
+                $exitValue = &compareStream("verified/$files[$j].stdout");
+                if ( $exitValue & 2 ) {
+
+                    # STDOUT verified doesn't exist. Search STDOUT capture
+                    # for strings indicating error or failure
+                    $exitValue |= &errorStrSearch("$files[$j].stdout");
+                }
+                if ( ( $exitValue & 8 ) || ( $exitValue & 64 ) ) {
+
+                    # Increment the total number of test failed
+                    $testDriverFailCount++;
+
+                    # Push test on failed list
+                    print(
+"Test failed ($failPoints out of $totalPoints testpoints failed)\n"
+                      )
+                      if ( !$silent );
+                    push( @testsFailed, $pwd . "/" . $files[$j] );
+                }
+                else {
+
+                    # Perform difference on STDERR file collection with verified
+                    $exitValue = &compareStream("verified/$files[$j].stderr");
+                    if ( $exitValue & 4 ) {
+
+                        # STDERR verified doesn't exist. Search STDERR capture
+                        # for strings indicating error or failure
+                        $exitValue |= &errorStrSearch("$files[$j].stderr");
+                    }
+                    if ( ( $exitValue & 16 ) || ( $exitValue & 128 ) ) {
+
+                        # Increment the total number of tests failed
+                        $testDriverFailCount++;
+
+                        # Push test on failed list
+                        print(
+"Test failed ($failPoints out of $totalPoints testpoints failed)\n"
+                          )
+                          if ( !$silent );
+                        push( @testsFailed, $pwd . "/" . $files[$j] );
+                    }
+                    else {
+                        print("Test successful ($totalPoints testpoints)\n")
+                          if ( !$silent );
+                    }
+                }
+            }
+        }
+        $j++;
+    }
+}
+
+################################################################################
+#
+#  SUBROUTINE: errorStrSearch
+#
+#      Description:  This subroutine will search the file specified in its
+#                    parameter for error strings and if they do exists
+#                    the appropriate value will be returned.
+#
+#      Parameter(s): fileName - input file to search for strings
+#
+#      Return:   0  -  No error strings found
+#               64  -  Error strings found in STDOUT
+#              128  -  Error strings found in STDERR
+#
+###############################################################################
+
+sub errorStrSearch {
+    local ($fileName)  = @_;
+    local ($returnVal) = 0;
+
+    # Open the captured file
+    open( CAPT_FILE, "<temp/$fileName" );
+
+    # Scan through all the lines of the file searching for error strings
+    while (<CAPT_FILE>) {
+        if (   m/FAIL/i
+            || m/FAULT/i
+            || m/ERROR/i
+            || m/Not Found/i
+            || m/SIGNAL/i
+            || m/NO SUCH FILE/i
+            || m/\|E\|/i
+            || m/\|A\|/i )
+        {
+            print;
+            if ( $fileName =~ m/out/ ) {
+                print(
+                    "        Failed - File $fileName contains error strings.\n"
+                );
+                $returnVal = 64;
+            }
+            elsif ( $fileName =~ m/err/ ) {
+                print(
+                    "        Failed - File $fileName contains error strings.\n"
+                );
+                $returnVal = 128;
+            }
+            last;
+        }
+    }
+
+    # Close the capture file
+    close(CAPT_FILE);
+
+    # Return the return value
+    return ($returnVal);
+}
+
+################################################################################
+#
+#  SUBROUTINE: compareStream
+#
+#      Description:  This subroutine will compare the captured stream file with
+#                    a file in the verified directory if one exists.
+#
+#      Parameter(s): streamFile - input file to compare
+#
+#      Return:   0  -  Compare successful
+#                2  -  STDOUT verified file doesn't exist
+#                4  -  STDERR verified file doesn't exist
+#                8  -  STDOUT verified file doesn't compare
+#               16  -  STDERR verified file doesn't compare
+#
+###############################################################################
+
+sub compareStream {
+    local ($streamFile) = @_;
+    local ($returnVal)  = 0;
+    local ($tempFile)   = "";
+
+    # Check for existence of verified STD stream files
+    if ( !( -e $streamFile ) ) {
+
+        # Display message to user that verified STDOUT file doesn't exist
+        print("        File $streamFile doesn't exist.\n") if ($verbose);
+
+        # Set exit value bit 1 to indicate proper failure
+        if ( $streamFile =~ /out$/ ) {
+            $returnVal |= 2;
+        }
+        elsif ( $streamFile =~ /err$/ ) {
+            $returnVal |= 4;
+        }
+    }
+    else {
+
+        # Verified STD stream file exists
+
+        # Create name of the temp file to compare
+        $tempFile = $streamFile;
+        $tempFile =~ s/verified/temp/;
+        $tempFile = $tempFile . ".mod";
+
+        # Perform difference on the STD stream files
+        $diffstdout = `diff $streamFile $tempFile`;
+
+        # Check the return value of the difference
+        if ( $? != 0 ) {
+
+            # Difference of STD stream files failed
+
+            # Check for STDOUT in file name to convey appropirate return value
+            if ( $streamFile =~ /out$/ ) {
+
+                # Display message of the failure of difference to user
+                print("        Failed - STDOUT difference\n$diffstdout\n");
+
+                # Exit value to indicate STDOUT did not compare
+                $returnVal |= 8;
+            }
+            elsif ( $streamFile =~ /err$/ ) {
+
+                # Display message of the failure of difference to user
+                print("        Failed - STDERR difference\n$diffstdout\n");
+
+                # Exit value to indicate STDERR did not compare
+                $returnVal |= 16;
+            }
+        }
+    }
+
+    # Return the result of the compare
+    return ($returnVal);
+}
+
+################################################################################
+#
+#  SUBROUTINE: checkForTempDirectory
+#
+#      Description:  This subroutine will check for the existence of a temp
+#                    directory to store STDOUT, STDERR files during test.  If
+#                    the subdirectory doesn't exist, it will be created.
+#
+#      Parameter(s):  None
+#
+#      Return: None
+#
+################################################################################
+
+sub checkForTempDirectory {
+
+    # Check if a temp directory already exists in the current work directory
+    if ( !( -e "temp" ) ) {
+
+        # Create temp directory to store STDOUT, STDERR files during test
+        `mkdir temp`;
+
+        # Display message of new directory created
+        print("Creating temp directory\n") if ($verbose);
+    }
+}
+
+################################################################################
+#
+#  SUBROUTINE: checkForVerifiedDirectory
+#
+#      Description:  This subroutine will check for the existence of a verified
+#                    directory which stores verified STDOUT, STDERR files for
+#                    comparison during the test.
+#
+#      Parameter(s):  None
+#
+#      Return: 0 - subdirectory present
+#              1 - subdirectory not present
+#
+################################################################################
+
+sub checkForVerifiedDirectory {
+    $returnValue = 0;
+
+    # Check if verified subdirectory exists in the current working directory
+    if ( !( -e "verified" ) ) {
+
+        # Set return value to 1
+        $returnValue = 1;
+    }
+    return ($returnValue);
+}
+
+################################################################################
+#
+#  SUBROUTINE: filterStdFiles
+#
+#      Description:  This subroutine will filter variable items in the STDOUT
+#                    and STDERR files captured.  Date, time and host names
+#                    are variable items in the log messages captured.
+#
+#      Parameter(s):  test file name
+#
+#      Return: None
+#
+################################################################################
+
+sub filterStdFiles {
+
+    local ($fileName) = @_;
+
+    # Open the STDOUT file for reading
+    open( OUTFILE, "< temp/$fileName.stdout" );
+
+    # Open mod file to place filtered STDOUT
+    open( MODFILE, "> temp/$fileName.stdout.mod" );
+
+    # Replace the variable data, time and host information with constants
+    $hostname = `hostname`;
+    chop $hostname;
+    while (<OUTFILE>) {
+        s/\s+\d+:\d+:\d+\w/<TIME>/g;
+        s/\d+:\d+:\d+/<DATE>/g;
+        s/$hostname/<HOST>/g;
+        s/: Line \d+/: Line <LINENO>/g;
+        s/\:\d+/\:<LINENO>/g;
+        s/allocate \d+ bytes at/allocate <N> bytes at/g;
+
+        # Filter lines with *** malloc.  This is an artifact of Mac testing of
+        # memory functions
+        if ( !m/\*\*\*\smalloc/ ) {
+            print MODFILE ($_);
+        }
+    }
+
+    # Close mod file
+    close(MODFILE);
+
+    # Close STDERR file
+    close(OUTFILE);
+
+    # Open the STDERR file for reading
+    open( OUTFILE, "< temp/$fileName.stderr" );
+
+    # Open mod file to place filtered STDERR
+    open( MODFILE, "> temp/$fileName.stderr.mod" );
+
+    # Replace the variable date, time and host information with constants
+    while (<OUTFILE>) {
+        s/\s+\d+:\d+:\d+\w/<TIME>/g;
+        s/\d+:\d+:\d+/<DATE>/g;
+        s/$hostname/<HOST>/g;
+        s/: Line \d+/: Line <LINENO>/g;
+        s/\:\d+/\:<LINENO>/g;
+        s/allocate \d+ bytes at/allocate <N> bytes at/g;
+
+        # Filter lines with *** malloc.  This is an artifact of Mac testing of
+        # memory functions
+        if ( !m/\*\*\*\smalloc/ ) {
+            print MODFILE ($_);
+        }
+    }
+
+    # Close mod file
+    close(MODFILE);
+
+    # Close STDERR file
+    close(OUTFILE);
+}
+
Index: /tags/rel2_1/psLib/test/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/Makefile	(revision 1553)
@@ -0,0 +1,103 @@
+##############################################################################
+##
+##  Makefile:   test
+##
+##  $Revision: 1.8 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-03 20:42:30 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+###############################################################################
+
+# Define variable prefix to the top level project - psLib
+# This is necessary for definition is Makefile.Globals uses prefix
+
+ifndef prefix
+    export prefix=$(shell cd ..;pwd)
+endif
+
+# Define the two targets to be built
+
+TARGET_STATIC  = libpstest.a
+TARGET_DYNAMIC = libpstest.$(DLL)
+
+# Include the make global definitions for the project
+
+include ../src/Makefile.Globals
+
+# Set CFLAGS used by the implicit rule to compile .c
+
+CFLAGS := $(CFLAGS_RELOC) -I../include
+
+# Define the source objects
+ 
+SRC_OBJS = psTest.o
+
+# Define PHONY target "all" which will make all the necessary items
+
+all: $(TARGET_STATIC) $(TARGET_DYNAMIC)
+
+# Rule to make static library
+
+libpstest.a: $(SRC_OBJS)
+# The ar option -r is to add/replace object and -s is to create
+# a symbol table in the archive
+	$(AR) rcs $@ $(SRC_OBJS)
+
+# Rule to make dynamic library
+
+libpstest.$(DLL): $(SRC_OBJS)
+	$(CC) $(LDFLAGS_DLL) -L../lib -lpslib $(SRC_OBJS) -o $@  
+
+# Define PHONY target "install" which will install necessary files
+
+install: $(TARGET_STATIC) $(TARGET_DYNAMIC) $(includedir) $(libexecdir) 
+	install *.h $(includedir)
+	install $(TARGET_STATIC) $(libexecdir)
+	install $(TARGET_DYNAMIC) $(libexecdir)
+
+installtests: install $(testbindir)
+	install FullUnitTest runTest $(testbindir)
+	$(MAKE) --directory=collections install
+	$(MAKE) --directory=image install
+	$(MAKE) --directory=dataManip install
+	$(MAKE) --directory=sysUtils install
+	$(MAKE) --directory=astronomy install
+
+# Define PHONY target "distclean" which will cleanup the distribution
+
+distclean:	clean
+	$(MAKE) --directory=collections distclean
+	$(MAKE) --directory=image distclean
+	$(MAKE) --directory=dataManip distclean
+	$(MAKE) --directory=sysUtils distclean
+	$(RM) $(TARGET_STATIC)
+	$(RM) $(TARGET_DYNAMIC)
+	$(RM) $(libexecdir)/$(TARGET_STATIC)
+	$(RM) $(libexecdir)/$(TARGET_DYNAMIC)
+
+# Define PHONY target "clean" which will cleanup the development area
+
+clean:
+	$(MAKE) --directory=collections clean
+	$(MAKE) --directory=image clean
+	$(MAKE) --directory=dataManip clean
+	$(MAKE) --directory=sysUtils clean
+	@echo "    Deleting intermediate files for 'test'"
+	$(RM) $(SRC_OBJS) *.lint
+
+%.lint: %.c
+	splint +posixlib -exportlocal -realcompare $(INCLUDE_GLOBAL) $? > $@; cat $@
+
+# Rule to make include directory if needed
+
+$(includedir):
+	mkdir -p $(includedir)
+
+# Rule to make lib directory if needed
+
+$(libexecdir):
+	mkdir -p $(libexecdir)
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
Index: /tags/rel2_1/psLib/test/astronomy/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/.cvsignore	(revision 1553)
@@ -0,0 +1,10 @@
+temp
+tst_psTime_01
+tst_psTime_02
+tst_psMetadata05_OUT
+tst_psMetadata_01
+tst_psMetadata_02
+tst_psMetadata_03
+tst_psMetadata_04
+tst_psMetadata_05
+tst_psMetadata_06
Index: /tags/rel2_1/psLib/test/astronomy/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/Makefile	(revision 1553)
@@ -0,0 +1,50 @@
+################################################################################
+##
+##  Makefile:   test/astronomy
+##
+##  $Revision: 1.11.2.1 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-16 23:59:01 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+include ../../src/Makefile.Globals
+
+CFLAGS := -I../../include $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+
+TARGET = tst_psTime_01 \
+         tst_psTime_02 \
+         tst_psMetadata_01 \
+         tst_psMetadata_02 \
+         tst_psMetadata_03 \
+         tst_psMetadata_04 \
+         tst_psMetadata_05 \
+         tst_psMetadata_06
+
+OBJS = $(addprefix builddir/,$(addsuffix .o,$(TARGET)))
+
+all: $(TARGET)
+
+clean:
+	@echo "    Deleting executable and binary files for 'test/collections'"
+	$(RM) $(OBJS)
+
+distclean: clean
+	$(RM) $(TARGET)
+
+install: $(testbindir) $(testbindir)/verified $(TARGET)
+	install header_1.fits header_2.fits $(TARGET) $(testbindir)
+	install verified/*.stderr verified/*.stdout $(testbindir)/verified
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
+$(testbindir)/verified:
+	mkdir -p $(testbindir)/verified
+
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_01.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_01.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_01.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_01.o: tst_psMetadata_01.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_02.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_02.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_02.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_02.o: tst_psMetadata_02.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_03.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_03.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_03.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_03.o: tst_psMetadata_03.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_04.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_04.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_04.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_04.o: tst_psMetadata_04.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_05.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_05.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_05.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_05.o: tst_psMetadata_05.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_06.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_06.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psMetadata_06.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psMetadata_06.o: tst_psMetadata_06.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_01.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_01.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_01.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psTime_01.o: tst_psTime_01.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_02.d
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_02.d	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/builddir/tst_psTime_02.d	(revision 1553)
@@ -0,0 +1,15 @@
+builddir/tst_psTime_02.o: tst_psTime_02.c ../../include/pslib.h \
+  ../../include/psMemory.h ../../include/psLogMsg.h \
+  ../../include/psTrace.h ../../include/psAbort.h ../../include/psError.h \
+  ../../include/psString.h ../../include/psType.h ../../include/psList.h \
+  ../../include/psCompare.h ../../include/psArray.h \
+  ../../include/psHash.h ../../include/psScalar.h \
+  ../../include/psVector.h ../../include/psImage.h \
+  ../../include/psImageExtraction.h ../../include/psStats.h \
+  ../../include/psImageManip.h ../../include/psImageIO.h \
+  ../../include/psImageStats.h ../../include/psFunctions.h \
+  ../../include/psBitSet.h ../../include/psMatrix.h \
+  ../../include/psMatrixVectorArithmetic.h ../../include/psFFT.h \
+  ../../include/psMinimize.h ../../include/psCoord.h \
+  ../../include/psTime.h ../../include/psPhotometry.h \
+  ../../include/psMetadata.h ../../include/psTest.h
Index: /tags/rel2_1/psLib/test/astronomy/header_1.fits
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/header_1.fits	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/header_1.fits	(revision 1553)
@@ -0,0 +1,1 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                    8 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            HISTORY File modified by user 'harman' with fv  on 2004-08-04T11:11:18          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Index: /tags/rel2_1/psLib/test/astronomy/header_2.fits
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/header_2.fits	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/header_2.fits	(revision 1553)
@@ -0,0 +1,1 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BITPIX  =                  -64 / number of bits per data pixel                  EXTNAME = 'MY_DATA_1'                                                           HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:14:45          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:15:29          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:18          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:46          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     EXTNAME = 'MY_DATA_2'                                                           HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:12          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:52          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_01.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_01.c	(revision 1553)
@@ -0,0 +1,259 @@
+/** @file  tst_psMetadata_01.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Read 1st hdr from simple FITS file
+*     Test B - Read 2nd hdr from complex FITS file
+*     Test C - Read named hdr from complex FITS file
+*     Test D - Remove items with same name from all metadata
+*     Test E- Attempt to use null file descriptor
+*     Test F - Attempt to use two null inputs
+*     Test G - Attempt to use bad extNum/
+*     Test H - Attempt to use bad extNameTest
+*     Test I - Free psMetadataData
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-12 01:08:39 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
+
+static void printMetadataItemList(psList *metadataItemList)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListSetIterator(metadataItemList, PS_LIST_HEAD);
+    entryChild = psListGetCurrent(metadataItemList);
+    while (entryChild != NULL) {
+        printMetadataItem(entryChild, "    ");
+        entryChild = psListGetNext(metadataItemList);
+    }
+}
+
+static void printMetadataList(psList *metadataItemList)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListSetIterator(metadataItemList, PS_LIST_HEAD);
+    entryChild = psListGetCurrent(metadataItemList);
+    while (entryChild != NULL) {
+        printMetadataItem(entryChild, " ");
+        entryChild = psListGetNext(metadataItemList);
+    }
+}
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
+{
+    printf("%sKey Name: %8s  ", spaces, metadataItem->name);
+    printf("Key Type: %2d  ", metadataItem->type);
+
+    switch (metadataItem->type ) {
+    case PS_META_ITEM_SET:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+
+    if(metadataItem->items->size) {
+        printMetadataItemList(metadataItem->items);
+    }
+}
+
+static void printMetadataTable(psHash *mdTable)
+{
+    int i;
+    psHashBucket* ptr = NULL;
+    for(i=0; i<mdTable->nbucket; i++) {
+        ptr = mdTable->buckets[i];
+        while (ptr != NULL) {
+            printMetadataItem(ptr->data, " ");
+            ptr = ptr->next;
+        }
+    }
+}
+
+static void printMetadata(psMetadata *metadata)
+{
+    printf("Contents of metadata list:\n");
+    printMetadataList(metadata->list);
+    printf("\nContents of metadata table:\n");
+    printMetadataTable(metadata->table);
+}
+
+
+int main(int argc, char* argv[])
+{
+    int status = 0;
+    char fitsErr[ 256 ];
+    psMetadata *metadata1 = NULL;
+    psMetadata *metadata2 = NULL;
+    psMetadata *metadata3 = NULL;
+    fitsfile *fptr;
+
+
+    // Test A - Read 1st hdr from simple FITS file
+
+    /* Header contents for header_1.fits:
+
+        SIMPLE  =                    T / file does conform to FITS standard
+        BITPIX  =                    8 / number of bits per data pixel
+        NAXIS   =                    0 / number of data axes
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T11:11:18
+        END
+    */
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file");
+    fits_open_file(&fptr, "header_1.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata1 = psMetadataFReadHeader(metadata1, NULL, 1, fptr);
+    printMetadata(metadata1);
+    printFooter(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file", true);
+
+
+    // Test B - Test B - Read 2nd hdr from complex FITS file
+
+    /* Header contents for header_2.fits:
+
+        SIMPLE  =                    T / file does conform to FITS standard
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        EXTEND  =                    T / FITS dataset may contain extensions
+        COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy
+        COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H
+        END
+        <DATA>
+
+        XTENSION= 'IMAGE   '           / IMAGE extension
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        PCOUNT  =                    0 / required keyword; must = 0
+        GCOUNT  =                    1 / required keyword; must = 1
+        BITPIX  =                  -64 / number of bits per data pixel
+        EXTNAME = 'MY_DATA_1'
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:14:45
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:15:29
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:18
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:46
+        END
+        <DATA>
+
+        XTENSION= 'IMAGE   '           / IMAGE extension
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        PCOUNT  =                    0 / required keyword; must = 0
+        GCOUNT  =                    1 / required keyword; must = 1
+        EXTNAME = 'MY_DATA_2'
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:12
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:52
+        END
+        <DATA>
+    */
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file");
+    fits_open_file(&fptr, "header_2.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata2 = psMetadataFReadHeader(metadata2, NULL, 2, fptr);
+    printMetadata(metadata2);
+    printFooter(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file", true);
+
+
+    // Test C - Read named hdr from complex FITS file
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file");
+    fits_open_file(&fptr, "header_2.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata3 = psMetadataFReadHeader(metadata3, "MY_DATA_2", 0, fptr);
+    printMetadata(metadata3);
+    printFooter(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file", true);
+
+
+    // Test D - Remove items with same name from all metadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Remove items with same name from all metadata");
+    printf("Removed HISTORY from all metadata from prior test. Resulting metadata:\n\n");
+    psMetadataRemove(metadata3, 0, "HISTORY");
+    printMetadata(metadata3);
+    printFooter(stdout, "psMetadata", "Test D - Remove items with same name from all metadata", true);
+
+
+    // Test E - Attempt to use null file descriptor
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to use null file descriptor",
+                            "Null FITS file descriptor not allowed", 0);
+    psMetadataFReadHeader(NULL, NULL, 1, NULL);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to use null file descriptor", true);
+
+
+    // Test F - Attempt to use two null inputs
+    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to use two null inputs",
+                            "Null extName and extNum = 0 not allowed", 0);
+    psMetadataFReadHeader(NULL, NULL, 0, fptr);
+    printFooter(stdout, "psMetadata", "Test F - Attempt to use two null inputs", true);
+
+
+    // Test G - Attempt to use bad extNum
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use bad extNum",
+                            "FITS error while locating header 22: tried to move past end of file", 0);
+    psMetadataFReadHeader(metadata1, NULL, 22, fptr);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use bad extNum", true);
+
+
+    // Test H - Attempt to use bad extName
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use bad extName",
+                            "FITS error while locating header AARGH: illegal HDU number", 0);
+    psMetadataFReadHeader(metadata1, "AARGH", 0, fptr);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to use bad extName", true);
+
+
+    // Test I- Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test I - Free psMetadata");
+    psFree(metadata1);
+    psFree(metadata2);
+    psFree(metadata3);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test I - Free psMetadata", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_02.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_02.c	(revision 1553)
@@ -0,0 +1,140 @@
+/** @file  tst_psMetadata_02.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata items
+*     Test B - Attempt to create metadata item with null name
+*     Test C - Attempt to create metadata item with invalid type
+*     Test D - Allocate metadata
+*     Test E - Attempt to add metadata item to null metadata
+*     Test F - Attempt to add null metadata item to metadata
+*     Test G - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:49:50 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadata *metadata = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item5 = NULL;
+    psMetadataItem *badItem = NULL;
+
+
+    // Test A - Allocate metadata items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 111);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_F32, "I am a single precision floating point", 222.222);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_F64, "I am a double precision floating point", 333.333);
+    item5 = psMetadataItemAlloc("myItem5", PS_META_STR, "I am a string", "HELLO WORLD");
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printMetadataItem(item5);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Attempt to create metadata item with null name
+    printNegativeTestHeader(stdout,"psMetadata", "Test B - Attempt to create metadata item with null name",
+                            "Null value for name not allowed", 0);
+    psMetadataItemAlloc(NULL, PS_META_STR, "I am a string", "HELLO WORLD");
+    printFooter(stdout, "psMetadata", "Test B - Attempt to create metadata item with null name", true);
+
+
+    // Test C - Attempt to create metadata item with invalid type
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to create metadata item with invalid type",
+                            "Invalid psMetadataType: 6", 0);
+    badItem = psMetadataItemAlloc("badItem", PS_META_IMG, "I am bad", "Bad comment");
+    printFooter(stdout, "psMetadata", "Test C - Attempt to create metadata item with invalid type", true);
+
+
+    // Test D - Allocate metadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Allocate metadata");
+    metadata = psMetadataAlloc();
+    printFooter(stdout, "psMetadata", "Test D - Allocate metadata", true);
+
+
+    // Test E - Attempt add metadata item to null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to add metadata item to null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataAddItem(NULL, PS_LIST_HEAD, item1);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to add metadata item to null metadata", true);
+
+
+    // Test F - Attempt add null metadata item to metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to add null metadata item to metadata",
+                            "Null metadata item not allowed", 0);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, NULL);
+    printFooter(stdout, "psMetadata", "Test F - Attempt to add null metadata item to metadata", true);
+
+
+    // Test G - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Free psMetadata");
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(item5);
+    psFree(badItem);
+    psFree(metadata);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test G - Free psMetadata", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_03.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_03.c	(revision 1553)
@@ -0,0 +1,141 @@
+/** @file  tst_psMetadata_03.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Remove items from metadata by name
+*     Test C - Remove items from metadata by index
+*     Test D - Attempt to use null metadata
+*     Test E - Attempt to remove non-existant metadata item by name
+*     Test F - Attempt to remove non-existant metadata item by index
+*     Test G - Free psMetadata
+ *
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-09 20:20:02 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Remove items from metadata by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataRemove(metadata, 0, "myItem1" );
+    psMetadataRemove(metadata, 0, "myItem2" );
+    printFooter(stdout, "psMetadata", "Test B - Remove items from metadata by name", true);
+
+
+    // Test C - Remove items from metadata by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    psMetadataRemove(metadata, 0, NULL);
+    psMetadataRemove(metadata, 0, NULL );
+    printFooter(stdout, "psMetadata", "Test C - Remove items from metadata by index", true);
+
+
+    // Test D - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataRemove(NULL, 0, NULL);
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null metadata", true);
+
+
+    // Test E - Attempt to remove non-existant metadata item by name
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by name",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    psMetadataRemove(metadata, 0, "AARGH");
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by name", true);
+
+
+    // Test F - Attempt to remove non-existant metadata item by index
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by index",
+                            "Couldn't find metadata item in list. Index: 22", 0);
+    psMetadataRemove(metadata, 22, NULL);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by index", true);
+
+
+    // Test G - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test G - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_04.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_04.c	(revision 1553)
@@ -0,0 +1,165 @@
+
+/** @file  tst_psMetadata_04.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Lookup metadata item by name
+*     Test C - Attempt to use null metadata
+*     Test D - Attempt to use null key
+*     Test E - Attempt to lookup non-existant metadata item
+*     Test F - Lookup metadata item by index
+*     Test G - Attempt to use null metadata
+*     Test H - Attempt to get non-existant metadata item
+*     Test I - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:50:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Lookup metadata item by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Lookup metadata item by name");
+    item = psMetadataLookup(metadata, "myItem2");
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    }
+    printFooter(stdout, "psMetadata", "Test B - Lookup metadata item by name", true);
+
+
+    // Test C - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataLookup(NULL, "myItem2");
+    printFooter(stdout, "psMetadata", "Test C - Attempt to use null metadata", true);
+
+
+    // Test D - Attempt to use null key
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null key",
+                            "Null key name not allowed", 0);
+    psMetadataLookup(metadata, NULL);
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null key", true);
+
+
+    // Test E - Attempt to lookup non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to lookup non-existant metadata item",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    psMetadataLookup(metadata, "AARGH");
+    printFooter(stdout, "psMetadata", "Test E - Attempt to lookup non-existant metadata item", true);
+
+
+    // Test F - Lookup metadata item by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Lookup metadata item by index");
+    item = psMetadataGet(metadata, 0);
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    }
+    printFooter(stdout, "psMetadata", "Test F - Lookup metadata item by index", true);
+
+
+    // Test G - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    item = psMetadataGet(NULL, 0);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata", true);
+
+
+    // Test H - Attempt to get non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to get non-existant metadata item",
+                            "Couldn't find metadata item with given index. Index: 22", 0);
+    psMetadataGet(metadata, 22);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to get non-existant metadata item", true);
+
+
+    // Test I - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test I - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test I - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_05.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_05.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_05.c	(revision 1553)
@@ -0,0 +1,207 @@
+
+
+/** @file  tst_psMetadata_05.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test I - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 01:39:37 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    long data;
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item = NULL;
+    psMetadata *metadata = NULL;
+    FILE *fd = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Set iterator at second index
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Set iterator at second index");
+    psMetadataSetIterator(metadata, 2);
+    printFooter(stdout, "psMetadata", "Test B - Set iterator at second index", true);
+
+
+    // Test C - Get next item at index
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Get next item at index");
+    item = psMetadataGetNext(metadata, NULL, 2);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test C - Get next item at index", true);
+
+
+    // Test D - Get next item at index and string
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Get next item at index and string");
+    item = psMetadataGetNext(metadata, "myItem1", 1);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test D - Get next item at index and string", true);
+
+
+    // Test E - Get previous item at index
+    printPositiveTestHeader(stdout, "psMetadata", "Test E - Get previous item at index");
+    item = psMetadataGetPrevious(metadata, NULL, 1);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test E - Get previous item at index", true);
+
+
+    // Test F - Write metadata item to file
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Write metadata item to file");
+    fd = fopen("./tst_psMetadata05_OUT", "w");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for writing\n");
+    }
+    psMetadataItemPrint(fd, "%ld", item2);
+    printFooter(stdout, "psMetadata", "Test F - Write metadata item to file", true);
+    fclose(fd);
+    fd = fopen("./tst_psMetadata05_OUT", "r");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for reading\n");
+    }
+    fscanf(fd, "%ld", &data);
+    fclose(fd);
+    if(data != 55) {
+        printf("ERROR: Data in file is not as expected. Value: %ld. Should be: 55.\n", data);
+    }
+
+
+    // Test G - Attempt to use null metadata with setIterator
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata with setIterator",
+                            "Null metadata collection not allowed", 0);
+    psMetadataSetIterator(NULL, 0);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata with setIterator", true);
+
+
+    // Test H - Attempt to use null metadata with getNext
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use null metadata with getNext",
+                            "Null metadata collection not allowed", 0);
+    psMetadataGetNext(NULL, "myItem2", 0);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to use null metadata with getNext", true);
+
+
+    // Test I - Attempt to use null metadata with getPrevious
+    printNegativeTestHeader(stdout,"psMetadata", "Test I - Attempt to use null metadata with getPrevious",
+                            "Null metadata collection not allowed", 0);
+    psMetadataGetPrevious(NULL, "myItem2", 0);
+    printFooter(stdout, "psMetadata", "Test I - Attempt to use null metadata with getPrevious", true);
+
+
+    // Test J - Attempt to use null file with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test J - Attempt to use null file with itemPrint",
+                            "Null file descriptor not allowed", 0);
+    psMetadataItemPrint(NULL, "Item value: %ld", item2);
+    printFooter(stdout, "psMetadata", "Test J - Attempt to use null file with itemPrint", true);
+
+
+    // Test K - Attempt to use null format with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test K - Attempt to use null format with itemPrint",
+                            "Null format not allowed", 0);
+    psMetadataItemPrint(fd, NULL, item2);
+    printFooter(stdout, "psMetadata", "Test K - Attempt to use null format with itemPrint", true);
+
+
+    // Test L - Attempt to use null item with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test L - Attempt to use null item with itemPrint",
+                            "Null metadata not allowed", 0);
+    psMetadataItemPrint(fd, "Item value: %ld", NULL);
+    printFooter(stdout, "psMetadata", "Test L - Attempt to use null item with itemPrint", true);
+
+
+    // Test M - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test M - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test M - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_06.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_06.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psMetadata_06.c	(revision 1553)
@@ -0,0 +1,125 @@
+
+/** @file  tst_psMetadata_06.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Add leaf node on top of existing leaf node
+*     Test C - Add leaf node to existing folder node
+*     Test D - Add folder node on top of existing leaf node
+*     Test E - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:22:24 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1a = NULL;
+    psMetadataItem *item1b = NULL;
+    psMetadataItem *item1c = NULL;
+    psMetadataItem *item2a = NULL;
+    psMetadataItem *item2b = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata and items");
+    item1a = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item1b = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 111);
+    item1c = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 222);
+    item2a = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 333);
+    item2b = psMetadataItemAlloc("myItem2", PS_META_ITEM_SET, "I am a folder node", NULL);
+    metadata = psMetadataAlloc();
+    printMetadataItem(item1a);
+    printMetadataItem(item1b);
+    printMetadataItem(item1c);
+    printMetadataItem(item2a);
+    printMetadataItem(item2b);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata and items", true);
+
+
+    // Test B - Add leaf node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1a);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1b);
+    printFooter(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node", true);
+
+
+    // Test C - Add leaf node to existing folder node
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Add leaf node to existing folder node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1c);
+    printFooter(stdout, "psMetadata", "Test C - Add leaf node to existing folder node", true);
+
+
+    // Test D - Add folder node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2a);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2b);
+    printFooter(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node", true);
+
+
+    // Test E - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test E - Free psMetadata");
+    psFree(item1a);
+    psFree(item1b);
+    psFree(item1c);
+    psFree(item2a);
+    psFree(item2b);
+    psFree(metadata);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test E - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psTime_01.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psTime_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psTime_01.c	(revision 1553)
@@ -0,0 +1,157 @@
+/** @file  tst_psTime_01.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     A) Get current TAI time
+ *     B) Print test time
+ *     C) Convert psTime to ISO time
+ *     D) Convert ISO time to psTime
+ *     E) Convert psTime to UTC time
+ *     F) Convert UTC time to psTime
+ *     G) Convert psTime to MJD time
+ *     H) Convert MJD time to psTime
+ *     I) Convert psTime to JD time
+ *     J) Convert JD time to psTime
+ *     K) Convert psTime to timeval time
+ *     L) Convert timeval time to psTime
+ *     M) Convert psTime to tm time
+ *     N) Convert tm time to psTime
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+int main(int argc, char* argv[])
+{
+    psTime time;
+    psTime testTime;
+    char *testString = "2004/07/21,18:22:24.272";
+
+    // Test time was taken at July 21, 2004 at 18:22:24.272044
+    testTime.tv_sec = 1090434144;
+    testTime.tv_usec = 272044;
+
+
+    // Test A - Get current TAI time
+    printPositiveTestHeader(stdout,"psTime", "Get current TAI time");
+    time = psTimeGetTime();
+    printFooter(stdout, "psTime", "Get current TAI time", true);
+
+
+    //Test B - Print test time
+    printPositiveTestHeader(stdout,"psTime", "Print test time");
+    printf("Test time: Seconds = %ld Microseconds = %ld\n", (long)testTime.tv_sec, (long)testTime.tv_usec);
+    printFooter(stdout, "psTime", "Print test time", true);
+
+
+    // Test C - Convert psTime to ISO time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime to ISO time");
+    char *isoString;
+    isoString = psTimeToISO(testTime);
+    if(strncmp(isoString, testString, 256)) {
+        printf("ERROR - ISO string incorrect\n");
+        printf("Expected: %s\n", testString);
+        printf("Returned: %s\n", isoString);
+    }
+    printFooter(stdout, "psTime", "Convert psTime to ISO time", true);
+
+
+    // Test D - Convert ISO time to psTime
+    printPositiveTestHeader(stdout,"psTime", "Convert ISO time to psTime");
+    time = psISOToTime(isoString);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    psFree(isoString);
+    printFooter(stdout, "psTime", "Convert ISO time to psTime", true);
+
+
+    // Test E - Convert psTime to UTC time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime time to UTC time");
+    time = psTimeToUTC(testTime);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert psTime time to UTC time", true);
+
+
+    // Test F - Convert UTC time to psTime
+    printPositiveTestHeader(stdout,"psTime", "Convert UTC time to psTime");
+    time = psUTCToTime(time);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert UTC time to psTime", true);
+
+
+    // Test G - Convert psTime to MJD time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime to MJD time");
+    double mjdTime = 0.0;
+    mjdTime = psTimeToMJD(testTime);
+    printf("MJD = %f\n", mjdTime);
+    printFooter(stdout, "psTime", "Convert psTime to MJD time", true);
+
+
+    // Test H - Convert MJD time to psTime
+    printPositiveTestHeader(stdout,"psTime", "Convert MJD time to psTime");
+    time = psMJDToTime(mjdTime);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert MJD time to psTime", true);
+
+
+    // Test I - Convert psTime to JD time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime to JD time");
+    double jdTime = 0.0;
+    jdTime = psTimeToJD(testTime);
+    printf("JD = %f\n", jdTime);
+    printFooter(stdout, "psTime", "Convert psTime to JD time", true);
+
+
+    // Test J - Convert JD time to psTime
+    printPositiveTestHeader(stdout,"psTime", "Convert JD time to psTime");
+    time = psJDToTime(jdTime);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert JD time to psTime", true);
+
+
+    // Test K - Convert psTime to timeval time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime to timeval time");
+    struct timeval timevalTime;
+    timevalTime = psTimeToTimeval(testTime);
+    printf("timevalTime: Seconds = %ld Microseconds = %ld\n", (long)timevalTime.tv_sec, (long)timevalTime.tv_usec);
+    printFooter(stdout, "psTime", "Convert psTime to timeval time", true);
+
+
+    // Test L - Convert timeval time to psTime
+    printPositiveTestHeader(stdout,"psTime", "Convert timeval time to psTime");
+    time = psTimevalToTime(&timevalTime);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert timeval time to psTime", true);
+
+
+    // Test M - Convert psTime to tm time
+    printPositiveTestHeader(stdout,"psTime", "Convert psTime to tm time");
+    struct tm *tmTime;
+    tmTime = psTimeToTM(testTime);
+    printf("tmTime:\n");
+    printf("tmTime->tm_year = %d\n", tmTime->tm_year);
+    printf("tmTime->tm_mon = %d\n", tmTime->tm_mon);
+    printf("tmTime->tm_mday = %d\n", tmTime->tm_mday);
+    printf("tmTime->tm_hour = %d\n", tmTime->tm_hour);
+    printf("tmTime->tm_min = %d\n", tmTime->tm_min);
+    printf("tmTime->tm_sec = %d\n", tmTime->tm_sec);
+    printFooter(stdout, "psTime", "Convert psTime to tm time", true);
+
+
+    // Test N - Convert tm time to psTime
+    printPositiveTestHeader(stdout, "psTime", "Convert tm time to psTime");
+    time = psTMToTime(tmTime);
+    printf("psTime: Seconds = %ld Microseconds = %ld\n", (long)time.tv_sec, (long)time.tv_usec);
+    printFooter(stdout, "psTime", "Convert tm time to psTime", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/tst_psTime_02.c
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/tst_psTime_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/tst_psTime_02.c	(revision 1553)
@@ -0,0 +1,122 @@
+/** @file  tst_psTime_02.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     A) Attempt to use negative seconds
+ *     B) Attempt to use negative microseconds
+ *     C) Attempt to use negative time
+ *     D) Incorrect ISO time data
+ *     E) Attempt to use null timeval
+ *     F) Incorrect timeval time data
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc, char* argv[])
+{
+    psTime testTime;
+    struct timeval timevalTime;
+
+
+    // Test A - Attempt to use negative seconds
+    testTime.tv_sec = -1;
+    testTime.tv_usec = 1;
+    timevalTime.tv_sec = -1;
+    timevalTime.tv_usec = 1;
+    printNegativeTestHeader(stdout,"psTime", "Attempt to use negative seconds",
+                            "Negative seconds are not allowed: -1", 0);
+    psTimeToISO(testTime);
+    psTimeToUTC(testTime);
+    psUTCToTime(testTime);
+    psTimeToMJD(testTime);
+    psTimeToJD(testTime);
+    psTimeToTimeval(testTime);
+    psTimevalToTime(&timevalTime);
+    psTimeToTM(testTime);
+    printFooter(stdout, "psTime", "Attempt to use negative seconds", true);
+
+
+    // Test B - Attempt to use negative microseconds
+    testTime.tv_sec = 1;
+    testTime.tv_usec = -1;
+    timevalTime.tv_sec = 1;
+    timevalTime.tv_usec = -1;
+    printNegativeTestHeader(stdout,"psTime", "Attempt to use negative microseconds",
+                            "Negative microseconds are not allowed: -1", 0);
+    psTimeToISO(testTime);
+    psTimeToUTC(testTime);
+    psUTCToTime(testTime);
+    psTimeToMJD(testTime);
+    psTimeToJD(testTime);
+    psTimeToTimeval(testTime);
+    psTimevalToTime(&timevalTime);
+    psTimeToTM(testTime);
+    printFooter(stdout, "psTime", "Attempt to use negative microseconds", true);
+
+
+    // Test C - Attempt to use negative time
+    printNegativeTestHeader(stdout,"psTime", "Attempt to use negative time",
+                            "Negative time is not allowed: -1.000000", 0);
+    psJDToTime(-1.0);
+    psMJDToTime(-1.0);
+    printFooter(stdout, "psTime", "Attempt to use negative time", true);
+
+
+    // Test D - Incorrect ISO time data
+    printNegativeTestHeader(stdout,"psTime", "Incorrect ISO time data", "Time not allowed", 0);
+    psISOToTime("1800/2/2,12:12:12.122");
+    psISOToTime("2004/-2/2,12:12:12.122");
+    psISOToTime("2004/2/-2,12:12:12.122");
+    psISOToTime("2004/2/2,-12:12:12.122");
+    psISOToTime("2004/2/2,12:-12:12.122");
+    psISOToTime("2004/2/2,12:12:-12.122");
+    psISOToTime("2004/2/2,12:12:12.-122");
+    printFooter(stdout, "psTime", "Incorrect ISO time data", true);
+
+
+    // Test E - Attempt to use null timeval
+    printNegativeTestHeader(stdout,"psTime", "Attempt to use null timeval",
+                            "Null value for timeval arg not allowed", 0);
+    psTimevalToTime(NULL);
+    printFooter(stdout, "psTime", "Attempt to use null timeval", true);
+
+
+    // Test F - Incorrect timeval time data
+    printNegativeTestHeader(stdout,"psTime", "Incorrect timeval time data", "Time not allowed", 0);
+    struct tm tmTime;
+    tmTime.tm_year = -2;
+    tmTime.tm_mon  = 2;
+    tmTime.tm_mday = 2;
+    tmTime.tm_hour = 2;
+    tmTime.tm_min  = 2;
+    tmTime.tm_sec  = 2;
+    psTMToTime(&tmTime);
+    tmTime.tm_year = 100;
+    tmTime.tm_mon  = -2;
+    psTMToTime(&tmTime);
+    tmTime.tm_mon  = 2;
+    tmTime.tm_mday = -2;
+    psTMToTime(&tmTime);
+    tmTime.tm_hour = -2;
+    tmTime.tm_mday = 2;
+    psTMToTime(&tmTime);
+    tmTime.tm_hour = 2;
+    tmTime.tm_min = -2;
+    psTMToTime(&tmTime);
+    tmTime.tm_min = 2;
+    tmTime.tm_sec = -2;
+    psTMToTime(&tmTime);
+    printFooter(stdout, "psTime", "Incorrect timeval time data", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stderr	(revision 1553)
@@ -0,0 +1,4 @@
+<DATE><TIME>|<HOST>|E|psMetadataFRead|Null FITS file descriptor not allowed
+<DATE><TIME>|<HOST>|E|psMetadataFRead|Null extName and extNum = 0 not allowed
+<DATE><TIME>|<HOST>|E|psMetadataFRead|FITS error while locating header 22: tried to move past end of file
+<DATE><TIME>|<HOST>|E|psMetadataFRead|FITS error while locating header AARGH: illegal HDU number
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_01.stdout	(revision 1553)
@@ -0,0 +1,176 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test A - Read 1st hdr from simple FITS file}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+FITS file open status: OK - no error
+
+Contents of metadata list:
+ Key Name:   SIMPLE  Key Type:  1  Key Value:               1  Key Comment: file does conform to FITS standard
+ Key Name:   BITPIX  Key Type:  2  Key Value:               8  Key Comment: number of bits per data pixel
+ Key Name:    NAXIS  Key Type:  2  Key Value:               0  Key Comment: number of data axes
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+
+Contents of metadata table:
+ Key Name:    NAXIS  Key Type:  2  Key Value:               0  Key Comment: number of data axes
+ Key Name:   SIMPLE  Key Type:  1  Key Value:               1  Key Comment: file does conform to FITS standard
+ Key Name:   BITPIX  Key Type:  2  Key Value:               8  Key Comment: number of bits per data pixel
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+
+---> TESTPOINT PASSED (psMetadata{Test A - Read 1st hdr from simple FITS file} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test B - Read 2nd hdr from complex FITS file}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+FITS file open status: OK - no error
+
+Contents of metadata list:
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_1'  Key Comment: 
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+
+Contents of metadata table:
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   BITPIX  Key Type:  0  Key Value:                  Key Comment: 
+    Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+    Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:  HISTORY  Key Type:  0  Key Value:                  Key Comment: 
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_1'  Key Comment: 
+
+---> TESTPOINT PASSED (psMetadata{Test B - Read 2nd hdr from complex FITS file} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test C - Read named hdr from complex FITS file} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+FITS file open status: OK - no error
+
+Contents of metadata list:
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_2'  Key Comment: 
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+
+Contents of metadata table:
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:  HISTORY  Key Type:  0  Key Value:                  Key Comment: 
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+    Key Name:  HISTORY  Key Type:  5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_2'  Key Comment: 
+
+---> TESTPOINT PASSED (psMetadata{Test C - Read named hdr from complex FITS file} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test D - Remove items with same name from all metadata} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Removed HISTORY from all metadata from prior test. Resulting metadata:
+
+Contents of metadata list:
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_2'  Key Comment: 
+
+Contents of metadata table:
+ Key Name:    NAXIS  Key Type:  2  Key Value:               1  Key Comment: number of data axes
+ Key Name:   NAXIS1  Key Type:  2  Key Value:              64  Key Comment: length of data axis 1
+ Key Name:   PCOUNT  Key Type:  2  Key Value:               0  Key Comment: required keyword; must = 0
+ Key Name: XTENSION  Key Type:  5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
+ Key Name:   GCOUNT  Key Type:  2  Key Value:               1  Key Comment: required keyword; must = 1
+ Key Name:   BITPIX  Key Type:  2  Key Value:             -64  Key Comment: number of bits per data pixel
+ Key Name:  EXTNAME  Key Type:  5  Key Value:     'MY_DATA_2'  Key Comment: 
+
+---> TESTPOINT PASSED (psMetadata{Test D - Remove items with same name from all metadata} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test E - Attempt to use null file descriptor}   *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null FITS file descriptor not allowed                      *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Attempt to use null file descriptor} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test F - Attempt to use two null inputs}        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null extName and extNum = 0 not allowed                    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test F - Attempt to use two null inputs} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test G - Attempt to use bad extNum}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: FITS error while locating header 22: tried to move past end of file *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test G - Attempt to use bad extNum} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test H - Attempt to use bad extName}            *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: FITS error while locating header AARGH: illegal HDU number *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test H - Attempt to use bad extName} | tst_psMetadata_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_01.c                                        *
+*            TestPoint: psMetadata{Test I - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test I - Free psMetadata} | tst_psMetadata_01.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stderr	(revision 1553)
@@ -0,0 +1,4 @@
+<DATE><TIME>|<HOST>|E|psMetadataItemA|Null value for name not allowed
+<DATE><TIME>|<HOST>|E|psMetadataItemA|Invalid psMetadataType: 6
+<DATE><TIME>|<HOST>|E|psMetadataAddIt|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataAddIt|Null metadata item not allowed
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_02.stdout	(revision 1553)
@@ -0,0 +1,76 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test A - Allocate metadata items}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Key Name:  myItem1  Key Type:  1  Key Value:               1  Key Comment: I am a boolean
+Key Name:  myItem2  Key Type:  2  Key Value:             111  Key Comment: I am a signed integer
+Key Name:  myItem3  Key Type:  3  Key Value:         222.222  Key Comment: I am a single precision floating point
+Key Name:  myItem4  Key Type:  4  Key Value:         333.333  Key Comment: I am a double precision floating point
+Key Name:  myItem5  Key Type:  5  Key Value:     HELLO WORLD  Key Comment: I am a string
+
+---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata items} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test B - Attempt to create metadata item with null name} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null value for name not allowed                            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test B - Attempt to create metadata item with null name} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test C - Attempt to create metadata item with invalid type} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid psMetadataType: 6                                  *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test C - Attempt to create metadata item with invalid type} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test D - Allocate metadata}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test D - Allocate metadata} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test E - Attempt to add metadata item to null metadata} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Attempt to add metadata item to null metadata} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test F - Attempt to add null metadata item to metadata} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata item not allowed                             *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test F - Attempt to add null metadata item to metadata} | tst_psMetadata_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_02.c                                        *
+*            TestPoint: psMetadata{Test G - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test G - Free psMetadata} | tst_psMetadata_02.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stderr	(revision 1553)
@@ -0,0 +1,3 @@
+<DATE><TIME>|<HOST>|E|psMetadataRemov|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataRemov|Couldn't find metadata item. Name: AARGH
+<DATE><TIME>|<HOST>|E|psMetadataRemov|Couldn't find metadata item in list. Index: 22
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_03.stdout	(revision 1553)
@@ -0,0 +1,73 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test A - Allocate metadata items}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Key Name:  myItem1  Key Type:  1  Key Value:               1  Key Comment: I am a boolean
+Key Name:  myItem2  Key Type:  2  Key Value:              55  Key Comment: I am a integer
+Key Name:  myItem3  Key Type:  1  Key Value:               0  Key Comment: I am a boolean
+Key Name:  myItem4  Key Type:  2  Key Value:              66  Key Comment: I am a integer
+
+---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata items} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test B - Remove items from metadata by name}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test B - Remove items from metadata by name} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test C - Remove items from metadata by index}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test C - Remove items from metadata by index} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test D - Attempt to use null metadata}          *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test D - Attempt to use null metadata} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test E - Attempt to remove non-existant metadata item by name} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Couldn't find metadata item. Name: AARGH                   *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Attempt to remove non-existant metadata item by name} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test E - Attempt to remove non-existant metadata item by index} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Couldn't find metadata item in list. Index: 22             *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Attempt to remove non-existant metadata item by index} | tst_psMetadata_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_03.c                                        *
+*            TestPoint: psMetadata{Test G - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test G - Free psMetadata} | tst_psMetadata_03.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stderr	(revision 1553)
@@ -0,0 +1,5 @@
+<DATE><TIME>|<HOST>|E|psMetadataLooku|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataLooku|Null key name not allowed
+<DATE><TIME>|<HOST>|E|psMetadataLooku|Could not find metadata item. Key: AARGH
+<DATE><TIME>|<HOST>|E|  psMetadataGet|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|  psMetadataGet|Couldn't find metadata item with given index. Index: 22
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_04.stdout	(revision 1553)
@@ -0,0 +1,97 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test A - Allocate metadata items}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Key Name:  myItem1  Key Type:  1  Key Value:               1  Key Comment: I am a boolean
+Key Name:  myItem2  Key Type:  2  Key Value:              55  Key Comment: I am a integer
+Key Name:  myItem3  Key Type:  1  Key Value:               0  Key Comment: I am a boolean
+Key Name:  myItem4  Key Type:  2  Key Value:              66  Key Comment: I am a integer
+
+---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata items} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test B - Lookup metadata item by name}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Found item named myItem2
+
+---> TESTPOINT PASSED (psMetadata{Test B - Lookup metadata item by name} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test C - Attempt to use null metadata}          *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test C - Attempt to use null metadata} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test D - Attempt to use null key}               *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null key name not allowed                                  *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test D - Attempt to use null key} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test E - Attempt to lookup non-existant metadata item} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Couldn't find metadata item. Name: AARGH                   *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Attempt to lookup non-existant metadata item} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test F - Lookup metadata item by index}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Found item named myItem4
+
+---> TESTPOINT PASSED (psMetadata{Test F - Lookup metadata item by index} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test G - Attempt to use null metadata}          *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test G - Attempt to use null metadata} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test H - Attempt to get non-existant metadata item} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Couldn't find metadata item with given index. Index: 22    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test H - Attempt to get non-existant metadata item} | tst_psMetadata_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_04.c                                        *
+*            TestPoint: psMetadata{Test I - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test I - Free psMetadata} | tst_psMetadata_04.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stderr	(revision 1553)
@@ -0,0 +1,6 @@
+<DATE><TIME>|<HOST>|E|psMetadataSetIt|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataGetNe|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataGetPr|Null metadata collection not allowed
+<DATE><TIME>|<HOST>|E|psMetadataItemP|Null file descriptor not allowed
+<DATE><TIME>|<HOST>|E|psMetadataItemP|Null format not allowed
+<DATE><TIME>|<HOST>|E|psMetadataItemP|Null metadata not allowed
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_05.stdout	(revision 1553)
@@ -0,0 +1,136 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test A - Allocate metadata items}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Key Name:  myItem1  Key Type:  1  Key Value:               1  Key Comment: I am a boolean
+Key Name:  myItem2  Key Type:  2  Key Value:              55  Key Comment: I am a integer
+Key Name:  myItem3  Key Type:  1  Key Value:               0  Key Comment: I am a boolean
+Key Name:  myItem4  Key Type:  2  Key Value:              66  Key Comment: I am a integer
+
+---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata items} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test B - Set iterator at second index}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test B - Set iterator at second index} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test C - Get next item at index}                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Found item named myItem1
+
+---> TESTPOINT PASSED (psMetadata{Test C - Get next item at index} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test D - Get next item at index and string}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Found item named myItem1
+
+---> TESTPOINT PASSED (psMetadata{Test D - Get next item at index and string} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test E - Get previous item at index}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Found item named myItem4
+
+---> TESTPOINT PASSED (psMetadata{Test E - Get previous item at index} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test F - Write metadata item to file}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test F - Write metadata item to file} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test G - Attempt to use null metadata with setIterator} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test G - Attempt to use null metadata with setIterator} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test H - Attempt to use null metadata with getNext} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test H - Attempt to use null metadata with getNext} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test I - Attempt to use null metadata with getPrevious} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata collection not allowed                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test I - Attempt to use null metadata with getPrevious} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test J - Attempt to use null file with itemPrint} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null file descriptor not allowed                           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test J - Attempt to use null file with itemPrint} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test K - Attempt to use null format with itemPrint} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null format not allowed                                    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test K - Attempt to use null format with itemPrint} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test L - Attempt to use null item with itemPrint} *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null metadata not allowed                                  *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test L - Attempt to use null item with itemPrint} | tst_psMetadata_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_05.c                                        *
+*            TestPoint: psMetadata{Test M - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test M - Free psMetadata} | tst_psMetadata_05.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_06.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_06.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psMetadata_06.stdout	(revision 1553)
@@ -0,0 +1,50 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_06.c                                        *
+*            TestPoint: psMetadata{Test A - Allocate metadata and items}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Key Name:  myItem1  Key Type:  1  Key Value:               1  Key Comment: I am a boolean
+Key Name:  myItem1  Key Type:  2  Key Value:             111  Key Comment: I am a signed integer
+Key Name:  myItem1  Key Type:  2  Key Value:             222  Key Comment: I am a signed integer
+Key Name:  myItem2  Key Type:  2  Key Value:             333  Key Comment: I am a signed integer
+Key Name:  myItem2  Key Type:  0  Bad type: 0 Key Comment: I am a folder node
+
+---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata and items} | tst_psMetadata_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_06.c                                        *
+*            TestPoint: psMetadata{Test B - Add leaf node on top of existing leaf node} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test B - Add leaf node on top of existing leaf node} | tst_psMetadata_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_06.c                                        *
+*            TestPoint: psMetadata{Test C - Add leaf node to existing folder node} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test C - Add leaf node to existing folder node} | tst_psMetadata_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_06.c                                        *
+*            TestPoint: psMetadata{Test D - Add folder node on top of existing leaf node} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test D - Add folder node on top of existing leaf node} | tst_psMetadata_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMetadata_06.c                                        *
+*            TestPoint: psMetadata{Test E - Free psMetadata}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMetadata{Test E - Free psMetadata} | tst_psMetadata_06.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_01.stdout	(revision 1553)
@@ -0,0 +1,144 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Get current TAI time}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Get current TAI time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Print test time}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Test time: Seconds = 1090434144 Microseconds = 272044
+
+---> TESTPOINT PASSED (psTime{Print test time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime to ISO time}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Convert psTime to ISO time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert ISO time to psTime}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 272000
+
+---> TESTPOINT PASSED (psTime{Convert ISO time to psTime} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime time to UTC time}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434112 Microseconds = 272044
+
+---> TESTPOINT PASSED (psTime{Convert psTime time to UTC time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert UTC time to psTime}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 272044
+
+---> TESTPOINT PASSED (psTime{Convert UTC time to psTime} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime to MJD time}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+MJD = 53207.765559
+
+---> TESTPOINT PASSED (psTime{Convert psTime to MJD time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert MJD time to psTime}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 272043
+
+---> TESTPOINT PASSED (psTime{Convert MJD time to psTime} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime to JD time}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+JD = 2453208.265559
+
+---> TESTPOINT PASSED (psTime{Convert psTime to JD time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert JD time to psTime}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 272048
+
+---> TESTPOINT PASSED (psTime{Convert JD time to psTime} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime to timeval time}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+timevalTime: Seconds = 1090434144 Microseconds = 272044
+
+---> TESTPOINT PASSED (psTime{Convert psTime to timeval time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert timeval time to psTime}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 272044
+
+---> TESTPOINT PASSED (psTime{Convert timeval time to psTime} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert psTime to tm time}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+tmTime:
+tmTime->tm_year = 104
+tmTime->tm_mon = 6
+tmTime->tm_mday = 21
+tmTime->tm_hour = 18
+tmTime->tm_min = 22
+tmTime->tm_sec = 24
+
+---> TESTPOINT PASSED (psTime{Convert psTime to tm time} | tst_psTime_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_01.c                                            *
+*            TestPoint: psTime{Convert tm time to psTime}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+psTime: Seconds = 1090434144 Microseconds = 0
+
+---> TESTPOINT PASSED (psTime{Convert tm time to psTime} | tst_psTime_01.c)
+
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stderr	(revision 1553)
@@ -0,0 +1,32 @@
+<DATE><TIME>|<HOST>|E|    psTimeToISO|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psTimeToUTC|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psUTCToTime|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psTimeToMJD|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|     psTimeToJD|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|psTimeToTimeval|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|psTimevalToTime|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|     psTimeToTM|Negative seconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psTimeToISO|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psTimeToUTC|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psUTCToTime|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|    psTimeToMJD|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|     psTimeToJD|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|psTimeToTimeval|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|psTimevalToTime|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|     psTimeToTM|Negative microseconds are not allowed: -1
+<DATE><TIME>|<HOST>|E|     psJDToTime|Negative time is not allowed: -1.000000
+<DATE><TIME>|<HOST>|E|    psMJDToTime|Negative time is not allowed: -1.000000
+<DATE><TIME>|<HOST>|E|    psISOToTime|Years less than 1900 not allowed. Value: 1800
+<DATE><TIME>|<HOST>|E|    psISOToTime|Month must have a value from 1 to 12. Value: -2
+<DATE><TIME>|<HOST>|E|    psISOToTime|Day must have a value from 1 to 31. Value: -2
+<DATE><TIME>|<HOST>|E|    psISOToTime|Hour must have a value from 0 to 23. Value: -12
+<DATE><TIME>|<HOST>|E|    psISOToTime|Minute must have a value from 0 to 59. Value: -12
+<DATE><TIME>|<HOST>|E|    psISOToTime|Second must have a value from 0 to 59. Value: -12
+<DATE><TIME>|<HOST>|E|    psISOToTime|Millisecond must have a value from 0 to 999. Value: -122
+<DATE><TIME>|<HOST>|E|psTimevalToTime|Null value for timeval arg not allowed
+<DATE><TIME>|<HOST>|E|     psTMToTime|Input times earlier than 1970 not allowed. Value: 1898
+<DATE><TIME>|<HOST>|E|     psTMToTime|Month must have a value from 0 to 11. Value: -2
+<DATE><TIME>|<HOST>|E|     psTMToTime|Day must have a value from 1 to 31. Value: -2
+<DATE><TIME>|<HOST>|E|     psTMToTime|Hour must have a value from 0 to 23. Value: -2
+<DATE><TIME>|<HOST>|E|     psTMToTime|Minute must have a value from 0 to 59. Value: -2
+<DATE><TIME>|<HOST>|E|     psTMToTime|Second must have a value from 0 to 59. Value: -2
Index: /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/astronomy/verified/tst_psTime_02.stdout	(revision 1553)
@@ -0,0 +1,66 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Attempt to use negative seconds}                    *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Negative seconds are not allowed: -1                       *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Attempt to use negative seconds} | tst_psTime_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Attempt to use negative microseconds}               *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Negative microseconds are not allowed: -1                  *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Attempt to use negative microseconds} | tst_psTime_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Attempt to use negative time}                       *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Negative time is not allowed: -1.000000                    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Attempt to use negative time} | tst_psTime_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Incorrect ISO time data}                            *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Time not allowed                                           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Incorrect ISO time data} | tst_psTime_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Attempt to use null timeval}                        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null value for timeval arg not allowed                     *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Attempt to use null timeval} | tst_psTime_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTime_02.c                                            *
+*            TestPoint: psTime{Incorrect timeval time data}                        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Time not allowed                                           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTime{Incorrect timeval time data} | tst_psTime_02.c)
+
Index: /tags/rel2_1/psLib/test/collections/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/collections/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/.cvsignore	(revision 1553)
@@ -0,0 +1,30 @@
+temp
+Makefile
+tst_psBitSet_01
+tst_psBitSet_02
+tst_psBitSet_03
+tst_psBitSet_04
+tst_psBitSet_05
+tst_psBitSet_06
+tst_psBitSet_07
+tst_psBitSet_08
+tst_psImage
+tst_psSort_01
+tst_psSort_02
+tst_psSort_03
+tst_psSort_04
+tst_psVector_01
+tst_psVector_02
+tst_psVector_03
+tst_psList
+tst_psArray
+tst_psVector
+tst_psVectorSort_01
+tst_psVectorSort_02
+tst_psVectorSort_03
+tst_psVectorSort_04
+tst_psHash00
+tst_psHash01
+tst_psHash02
+tst_psHash03
+tst_psHash04
Index: /tags/rel2_1/psLib/test/collections/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/collections/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/Makefile	(revision 1553)
@@ -0,0 +1,63 @@
+################################################################################
+##
+##  Makefile:   test/collections
+##
+##  $Revision: 1.22 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-09 20:42:24 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+include ../../src/Makefile.Globals
+
+CFLAGS := -I../../include $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+
+TARGET = tst_psVector          \
+         tst_psArray           \
+         tst_psBitSet_01       \
+         tst_psBitSet_02       \
+         tst_psBitSet_03       \
+         tst_psBitSet_04       \
+         tst_psBitSet_05       \
+         tst_psBitSet_06       \
+         tst_psBitSet_07       \
+         tst_psBitSet_08       \
+         tst_psVectorSort_01   \
+         tst_psVectorSort_02   \
+         tst_psVectorSort_03   \
+         tst_psVectorSort_04   \
+         tst_psList            \
+         tst_psHash00          \
+         tst_psHash01          \
+         tst_psHash02          \
+         tst_psHash03          \
+         tst_psHash04
+
+OBJS = $(addsuffix .o,$(TARGET))
+
+all: $(TARGET)
+
+clean:
+	@echo "    Deleting executable and binary files for 'test/collections'"
+	$(RM) $(OBJS)
+
+distclean: clean
+	$(RM) $(TARGET)
+
+install: $(testbindir) $(testbindir)/verified $(TARGET)
+	install $(TARGET) $(testbindir)
+	install verified/*.stderr verified/*.stdout $(testbindir)/verified
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
+$(testbindir)/verified:
+	mkdir -p $(testbindir)/verified
+
+
Index: /tags/rel2_1/psLib/test/collections/tst_psArray.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psArray.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psArray.c	(revision 1553)
@@ -0,0 +1,155 @@
+/** @file  tst_psArray.c
+ *
+ *  @brief Test driver for psArray integer functions
+ *
+ *  This test driver contains the following tests for psArray test point 1:
+ *     A)  Create void pointer array
+ *     B)  Add data to void pointer array
+ *     C)  Reallocate void pointer array bigger
+ *     D)  Reallocate void pointer array smaller
+ *     E)  Free void pointer array
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <math.h>
+
+#include "pslib.h"
+#include "psTest.h"
+
+typedef struct
+{
+    int x;
+    float y;
+}
+testStruct;
+
+
+int main(int argc,
+         char* argv[])
+{
+    // Create array of pointers
+    testStruct *mySt[10];
+
+
+    // Test A - Create void pointer array
+    printPositiveTestHeader(stdout,"psArray", "Create void pointer array");
+    psArray *psArr = psArrayAlloc(5);
+    if (psArr->nalloc != 5) {
+        psError(__func__,"psArray didn't have proper number of elements.");
+        return 1;
+    }
+    printFooter(stdout, "psArray", "Create void pointer array", true);
+
+
+    // Test B - Add data to void pointer array
+    printPositiveTestHeader(stdout, "psArray", "Add data to void pointer array");
+    for(int i = 0; i < 5; i++) {
+        testStruct *ts = psAlloc(sizeof(testStruct));
+        ts->x = 10*i;
+        ts->y = 10.1*i;
+        mySt[i] = ts;
+        psArr->data[i] = ts;
+        psMemIncrRefCounter(ts);
+    }
+
+    for(int i = 0; i < 5; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        printf("ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(__func__,"Couldn't properly get elements from array.");
+            return 2;
+        }
+    }
+    printf("array size = %d\n", psArr->nalloc);
+    if (psArr->nalloc != 5) {
+        psError(__func__,"Array Size wrong");
+        return 3;
+    }
+    printf("array population = %d\n", psArr->n);
+    if (psArr->n != 5) {
+        psError(__func__,"Array population wrong");
+        return 4;
+    }
+    printFooter(stdout, "psArray", "Add data to void pointer array", true);
+
+
+    // Test C - Reallocate void pointer array bigger
+    printPositiveTestHeader(stdout,"psArray", "Reallocate void pointer array bigger");
+    psArr = psArrayRealloc(10, psArr);
+    printf("Adding more elements to void pointer array...\n");
+    for(int i = 5; i < 10; i++) {
+        testStruct *ts = psAlloc(sizeof(testStruct));
+        ts->x = 10*i;
+        ts->y = 10.1*i;
+        mySt[i] = ts;
+        psArr->data[i] = ts;
+        psArr->n++;
+        psMemIncrRefCounter(ts);
+    }
+    for(int i = 0; i < 10; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        printf("ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(__func__,"Couldn't properly get elements from array.");
+            return 5;
+        }
+    }
+    printf("array size = %d\n", psArr->nalloc);
+    if (psArr->nalloc != 10) {
+        psError(__func__,"Array Size wrong");
+        return 6;
+    }
+    printf("array population = %d\n", psArr->n);
+    if (psArr->n != 10) {
+        psError(__func__,"Array Population wrong");
+        return 7;
+    }
+    printFooter(stdout, "psArray", "Reallocate void pointer array bigger", true);
+
+
+    // Test D - Reallocate void pointer array smaller
+    printPositiveTestHeader(stdout,"psArray","Reallocate void pointer array smaller");
+    psArr = psArrayRealloc(3, psArr);
+    for(int i = 0; i < 3; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        printf("ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(__func__,"Couldn't properly get elements from array.");
+            return 8;
+        }
+    }
+    printf("array size = %d\n", psArr->nalloc);
+    if (psArr->nalloc != 3) {
+        psError(__func__,"Array Size wrong");
+        return 9;
+    }
+    printf("array population = %d\n", psArr->n);
+    if (psArr->n != 3) {
+        psError(__func__,"Array Population wrong");
+        return 10;
+    }
+    printFooter(stdout, "psArray", "Reallocate integer void pointer smaller", true);
+
+
+    // Test E - Free void pointer array
+    printPositiveTestHeader(stdout, "psArray", "Free void pointer array");
+    psFree(psArr);
+    for(int i = 0; i < 10; i++) {
+        psFree(mySt[i]);
+    }
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psArray" ,"Free void pointer array", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_01.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_01.c	(revision 1553)
@@ -0,0 +1,133 @@
+/** @file  tst_psBitSet_01.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 1:
+ *     A)  Create psBitSet
+ *     B)  Set bits
+ *     C)  Test bits
+ *     D)  Attempt to test negative bit
+ *     E)  Attempt to test bit to large
+ *     F)  Attempt to test bit in null BitSet
+ *     G)  Attempt to set negative bit
+ *     H)  Attempt to set bit to large
+ *     I)  Attempt to set bit in null BitSet
+ *     J)  Free psBitSet
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+    psBitSet *tempBs = NULL;
+
+
+    // Test A - Create psBitSet
+    printPositiveTestHeader(stdout,"psBitSet", "Create psBitSet");
+    printf("Creating psBitSet with 24 bits...\n");
+    psBitSet* bs = psBitSetAlloc(24);
+    binOut = psBitSetToString(bs);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create psBitSet", true);
+
+
+    // Test B - Set bits
+    printPositiveTestHeader(stdout, "psBitSet", "Set bits");
+    tempBs = bs;
+    printf("Setting first bit...\n");
+    bs = psBitSetSet(bs, 0);
+    printf("Setting third bit...\n");
+    bs = psBitSetSet(bs, 2);
+    printf("Setting last bit...\n");
+    bs = psBitSetSet(bs, 23);
+    if(bs != tempBs) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    binOut = psBitSetToString(bs);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Set bits", true);
+
+
+    // Test C - Test bits
+    printPositiveTestHeader(stdout, "psBitSet", "Test bits");
+    printf("Testing first bit...\n");
+    printf("Result: %d\n", psBitSetTest(bs, 0));
+    printf("Testing third bit...\n");
+    printf("Result: %d\n", psBitSetTest(bs, 2));
+    printf("Testing last bit...\n");
+    printf("Result: %d\n", psBitSetTest(bs, 23));
+    printFooter(stdout, "psBitSet", "Test bits", true);
+
+
+    // Test D - Attempt to test negative bit
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to test negative bit",
+                            "Bit position too small: -4", 0);
+    if(psBitSetTest(bs, -4)) {
+        printf("Error: Return value should be zero\n");
+    }
+    printFooter(stdout, "psBitSet", "Attempt to test negative bit", true);
+
+
+    // Test E - Attempt to test bit to large
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to test bit to large",
+                            "Bit position too large: 200", 0);
+    if(psBitSetTest(bs, 200)) {
+        printf("Error: Return value should be zero\n");
+    }
+    printFooter(stdout, "psBitSet", "Attempt to test bit to large", true);
+
+
+    // Test F - Attempt to test bit in null BitSet
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to test bit in null BitSet",
+                            "Null psBitSet for inBitSet argument", 0);
+    psBitSetTest(NULL, 0);
+    printFooter(stdout, "psBitSet", "Attempt to test bit in null BitSet", true);
+
+
+    // Test G - Attempt to set negative bit
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to set negative bit",
+                            "Bit position too small: -4", 0);
+    bs = psBitSetSet(bs, -4);
+    printFooter(stdout, "psBitSet", "Attempt to set negative bit", true);
+
+
+    // Test H - Attempt to set bit to large
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to set bit to large",
+                            "Bit position too large: 200", 0);
+    bs = psBitSetSet(bs, 200);
+    printFooter(stdout, "psBitSet", "Attempt to set bit to large", true);
+
+
+    // Test I - Attempt to set bit in null BitSet
+    printNegativeTestHeader(stdout,"psBitSet", "Attempt to set bit in null BitSet",
+                            "Null psBitSet for inBitSet argument", 0);
+    psBitSetSet(NULL, 0);
+    printFooter(stdout, "psBitSet", "Attempt to set bit in null BitSet", true);
+
+
+    // Test J - Free psBitSet
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSet");
+    psFree(bs);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSet", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_02.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_02.c	(revision 1553)
@@ -0,0 +1,89 @@
+/** @file  tst_psBitSet_02.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 2:
+ *     A)  Create two psBitSets
+ *     B)  Perform binary AND with psBitSets
+ *     C)  Perform binary AND and auto allocate output
+ *     D)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+    char *binOut2 = NULL;
+
+
+    // Test A - Create two psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Create two psBitSets");
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printf("Setting all bits true...\n");
+    for(int i=0; i<24; i++) {
+        bs1 = psBitSetSet(bs1, i);
+        bs2 = psBitSetSet(bs2, i);
+    }
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create two psBitSets", true);
+
+    // Test B - Perform binary AND with psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Perform binary AND with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "AND", bs2);
+    binOut = psBitSetToString(outbs);
+    printf("Result:\n");
+    printf("%s\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Perform binary AND with psBitSets", true);
+
+
+    // Test C - Perform binary AND and auto allocate output
+    printPositiveTestHeader(stdout,"psBitSet", "Perform binary AND and auto allocate output");
+    psBitSet* outbs2 = NULL;
+    outbs2 = psBitSetOp(outbs2, bs1, "AND", bs2);
+    binOut2 = psBitSetToString(outbs2);
+    printf("Result:\n");
+    printf("%s\n", binOut2);
+    psFree(binOut2);
+    printFooter(stdout, "psBitSet", "Perform binary AND and auto allocate output", true);
+
+
+    // Test D - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+    psFree(outbs2);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_03.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_03.c	(revision 1553)
@@ -0,0 +1,76 @@
+/** @file  tst_psBitSet_03.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 3:
+ *     A)  Create two psBitSets
+ *     B)  Perform binary OR with psBitSets
+ *     C)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+
+
+    // Test A - Create two psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Create two psBitSets");
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printf("Setting all bits true...\n");
+    for(int i=0; i<24; i++) {
+        bs1 = psBitSetSet(bs1, i);
+        bs2 = psBitSetSet(bs2, i);
+    }
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create two psBitSets", true);
+
+
+    // Test B - Perform binary OR with psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Perform binary OR with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "OR", bs2);
+    binOut = psBitSetToString(outbs);
+    printf("Result:\n");
+    printf("%s\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Perform binary OR with psBitSets", true);
+
+
+    // Test C - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_04.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_04.c	(revision 1553)
@@ -0,0 +1,76 @@
+/** @file  tst_psBitSet_04.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 4:
+ *     A)  Create two psBitSets
+ *     B)  Perform binary XOR with psBitSets
+ *     C)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+
+
+    // Test A - Create two psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Create two psBitSets");
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printf("Setting all bits true...\n");
+    for(int i=0; i<24; i++) {
+        bs1 = psBitSetSet(bs1, i);
+        bs2 = psBitSetSet(bs2, i);
+    }
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create two psBitSets", true);
+
+
+    // Test B - Perform binary XOR with psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Perform binary XOR with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "XOR", bs2);
+    binOut = psBitSetToString(outbs);
+    printf("Result:\n");
+    printf("%s\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Perform binary XOR with psBitSets", true);
+
+
+    // Test C - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_05.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_05.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_05.c	(revision 1553)
@@ -0,0 +1,61 @@
+/** @file  tst_psBitSet_05.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 5:
+ *     A)  Create two psBitSets of different size
+ *     B)  Attempt OR with psBitsets, should get error
+ *     C)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+
+
+    // Test A - Create two psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Create two psBitSets of different size");
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(40);
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create two psBitSets of different size", true);
+
+
+    // Test B - Attempt OR with psBitsets, should get error
+    printNegativeTestHeader(stdout, "psBitSet", "Attempt OR with psBitsets", "psBitSet sizes not the same", 0);
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "OR", bs2);
+    printFooter(stdout, "psBitSet", "Attempt OR with psBitsets", true);
+
+
+    // Test C - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_06.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_06.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_06.c	(revision 1553)
@@ -0,0 +1,70 @@
+/** @file  tst_psBitSet_06.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 6:
+ *     A)  Create two psBitSets
+ *     B)  Perform invalid binary operation with psBitSets
+ *     C)  Attempt to create negative size bitset
+ *     D   Attempt to free null BitSet
+ *     E)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.9 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut = NULL;
+
+
+    // Test A - Create two psBitSets
+    printPositiveTestHeader(stdout,"psBitSet", "Create two psBitSets");
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    binOut = psBitSetToString(bs1);
+    printf("%s\n", binOut);
+    psFree(binOut);
+    binOut = psBitSetToString(bs2);
+    printf("%s\n\n", binOut);
+    psFree(binOut);
+    printFooter(stdout, "psBitSet", "Create two psBitSets", true);
+
+
+    // Test B - Perform invalid binary operation with psBitSets
+    printNegativeTestHeader(stdout,"psBitSet", "Perform invalid binary operation",
+                            "Invalid psBitMask binary operation", 0);
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "ZZXOR", bs2);
+    printFooter(stdout, "psBitSet", "Perform binary XOR with psBitSets", true);
+
+
+    // Test C - Attempt to create negative size bitset
+    printNegativeTestHeader(stdout,"psBitSet", "Create negative size bitset",
+                            "Allocation size must be >= 0: size = -4", 0);
+    psBitSetAlloc(-4);
+    printFooter(stdout, "psBitSet", "Create negative size bitset", true);
+
+    // Test E - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSetFree psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_07.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_07.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_07.c	(revision 1553)
@@ -0,0 +1,95 @@
+
+/** @file  tst_psBitSet_07.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 7:
+ *     A)  Create psBitSets of non-multiple of 8 bits
+ *     B)  Set psBitSets to 0x3 and 0x5
+ *     C)  Perform AND, OR, and XOR
+ *     D)  Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+    char *binOut3 = NULL;
+
+    // Test A - Create psBitSet
+    printPositiveTestHeader(stdout,"psBitSet", "Create psBitSets of non-multiple of 8 bits");
+    printf("Creating psBitSets\n");
+    psBitSet* bs1 = psBitSetAlloc(3);
+    psBitSet* bs2 = psBitSetAlloc(3);
+    psBitSet* bs3 = psBitSetAlloc(3);
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    printf("%s\n", binOut1);
+    printf("%s\n\n", binOut2);
+    psFree(binOut1);
+    psFree(binOut2);
+    printFooter(stdout, "psBitSet", "Create psBitSets of non-multiple of 8 bits", true);
+
+
+    // Test B - Set bits to 0x3 and 0x5
+    printPositiveTestHeader(stdout, "psBitSet", "Set psBitSets to 0x3 and 0x5");
+    bs1 = psBitSetSet(bs1, 0);
+    bs1 = psBitSetSet(bs1, 1);
+    bs2 = psBitSetSet(bs2, 0);
+    bs2 = psBitSetSet(bs2, 2);
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    printf("%s\n", binOut1);
+    printf("%s\n\n", binOut2);
+    psFree(binOut1);
+    psFree(binOut2);
+    printFooter(stdout, "psBitSet", "Set psBitSets to 0x3 and 0x5", true);
+
+
+    // Test C - Perform AND, OR, and XOR
+    printPositiveTestHeader(stdout, "psBitSet", "Perform AND, OR, and XOR");
+    printf("AND:\n");
+    bs3 = psBitSetOp(bs3, bs1, "AND", bs2);
+    binOut3 = psBitSetToString(bs3);
+    printf("%s\n", binOut3);
+    psFree(binOut3);
+    printf("OR:\n");
+    bs3 = psBitSetOp(bs3, bs1, "OR", bs2);
+    binOut3 = psBitSetToString(bs3);
+    printf("%s\n", binOut3);
+    psFree(binOut3);
+    printf("XOR:\n");
+    bs3 = psBitSetOp(bs3, bs1, "XOR", bs2);
+    binOut3 = psBitSetToString(bs3);
+    printf("%s\n", binOut3);
+    psFree(binOut3);
+    printFooter(stdout, "psBitSet", "Perform AND, OR, and XOR", true);
+
+
+    // Test D - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(bs3);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psBitSet_08.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psBitSet_08.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psBitSet_08.c	(revision 1553)
@@ -0,0 +1,116 @@
+/** @file  tst_psBitSet_08.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 8:
+ *     A) Create psBitSets and set to 0xAA and 0xFF 0xCC
+ *     B) Perform NOT operation and auto allocate output
+ *     C) Attempt NOT operation if input argument is NULL
+ *     D) Free psBitSets
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+    char *binOut3 = NULL;
+    psBitSet *bsOut1 = NULL;
+    psBitSet *bsOut2 = NULL;
+    psBitSet *bsOut3 = NULL;
+
+
+    // Test A - Create psBitSets and set to 0xAA and 0xFF 0xCC
+    printPositiveTestHeader(stdout,"psBitSet", "Create psBitSets and set to 0xAA and 0xFF 0xCC");
+    printf("Creating psBitSets\n");
+    psBitSet* bs1 = psBitSetAlloc(8);
+    psBitSet* bs2 = psBitSetAlloc(8);
+    psBitSet* bs3 = psBitSetAlloc(8);
+
+    // Create 0xAA
+    bs1 = psBitSetSet(bs1, 1);
+    bs1 = psBitSetSet(bs1, 3);
+    bs1 = psBitSetSet(bs1, 5);
+    bs1 = psBitSetSet(bs1, 7);
+
+    // Create 0xFF
+    bs2 = psBitSetSet(bs2, 0);
+    bs2 = psBitSetSet(bs2, 1);
+    bs2 = psBitSetSet(bs2, 2);
+    bs2 = psBitSetSet(bs2, 3);
+    bs2 = psBitSetSet(bs2, 4);
+    bs2 = psBitSetSet(bs2, 5);
+    bs2 = psBitSetSet(bs2, 6);
+    bs2 = psBitSetSet(bs2, 7);
+
+    // Create 0xCC
+    bs3 = psBitSetSet(bs3, 2);
+    bs3 = psBitSetSet(bs3, 3);
+
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    binOut3 = psBitSetToString(bs3);
+    printf("%s\n", binOut1);
+    printf("%s\n", binOut2);
+    printf("%s\n\n", binOut3);
+    psFree(binOut1);
+    psFree(binOut2);
+    psFree(binOut3);
+    printFooter(stdout, "psBitSet", "Create psBitSets and set to 0xAA and 0xFF 0xCC", true);
+
+
+    // Test B - Perform NOT operation and auto allocate output argument
+    printPositiveTestHeader(stdout, "psBitSet", "Perform NOT operation and auto allocate output");
+    bsOut1 = psBitSetNot(bsOut1, bs1);
+    bsOut2 = psBitSetNot(bsOut2, bs2);
+    bsOut3 = psBitSetNot(bsOut3, bs3);
+    binOut1 = psBitSetToString(bsOut1);
+    binOut2 = psBitSetToString(bsOut2);
+    binOut3 = psBitSetToString(bsOut3);
+    printf("%s\n", binOut1);
+    printf("%s\n", binOut2);
+    printf("%s\n\n", binOut3);
+    psFree(binOut1);
+    psFree(binOut2);
+    psFree(binOut3);
+    printFooter(stdout, "psBitSet", "Perform NOT operation and auto allocate output", true);
+
+
+    // Test C - Attempt NOT operation if input argument is NULL
+    printNegativeTestHeader(stdout, "psBitSet", "Attempt NOT operation if input argument is NULL",
+                            "Null psBitSet for inBitSet argument", 0);
+    if(psBitSetNot(NULL, NULL) != NULL) {
+        printf("ERROR: Output psBitset should be NULL\n");
+    }
+    printFooter(stdout, "psBitSet", "Attempt NOT operation if input argument is NULL", true);
+
+
+    // Test D - Free psBitSets
+    printPositiveTestHeader(stdout, "psBitSet", "Free psBitSets");
+    psFree(bs1);
+    psFree(bs2);
+    psFree(bs3);
+    psFree(bsOut1);
+    psFree(bsOut2);
+    psFree(bsOut3);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psBitSet", "Free psBitSets", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psHash00.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psHash00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psHash00.c	(revision 1553)
@@ -0,0 +1,64 @@
+/*****************************************************************************
+    This code will test whether a hash table can be allocated successfully,
+    then deallocated successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 10
+int main()
+{
+    psHash *myHashTable = NULL;
+    int testStatus      = true;
+    int i               = 0;
+    int currentId = psMemGetId();
+    int memLeaks        = 0;
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashAlloc()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+
+    if (myHashTable == NULL) {
+        fprintf(stderr, "%s: could not allocate a hash table.", __func__);
+        testStatus = false;
+    }
+
+    if (myHashTable->nbucket != NUM_HASH_TABLE_BUCKETS) {
+        fprintf(stderr, "%s: myHashTable->nbucket not set properly.\n",
+                __func__);
+        testStatus = false;
+
+    }
+
+    if (myHashTable->buckets == NULL) {
+        fprintf(stderr, "%s: myHashTable->buckets is NULL.\n",
+                __func__);
+        testStatus = false;
+
+    }
+
+    for (i=0;i<NUM_HASH_TABLE_BUCKETS;i++) {
+        if (myHashTable->buckets[i] != NULL) {
+            fprintf(stderr, "%s: hash table bucket[%d] not equal to NULL.\n",
+                    __func__, i);
+            testStatus = false;
+        }
+    }
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashAlloc()",
+                testStatus);
+
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psHash01.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psHash01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psHash01.c	(revision 1553)
@@ -0,0 +1,79 @@
+/*****************************************************************************
+    This code will test whether a hash table can be de-allocated successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+int imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    p_psMemSetDeallocator(id,(psFreeFcn)IdFree);
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+int main()
+{
+    psHash *myHashTable = NULL;
+    int testStatus      = true;
+    int currentId = psMemGetId();
+    ID* id = NULL;
+    int memLeaks        = 0;
+
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashFree()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    id = IdAlloc("IDA");
+    psHashAdd(myHashTable, "ENTRY00", id);
+    psFree(id);
+    id = IdAlloc("IDB");
+    psHashAdd(myHashTable, "ENTRY01", id);
+    psFree(id);
+    id = IdAlloc("IDC");
+    psHashAdd(myHashTable, "ENTRY02", id);
+    psFree(id);
+    id = IdAlloc("IDD");
+    psHashAdd(myHashTable, "ENTRY03", id);
+    psFree(id);
+    psFree(myHashTable);
+
+    if (imGlobal != 4) {
+        fprintf(stderr, "%s: only (%d/4) entries were freed",
+                __func__, imGlobal);
+        testStatus = false;
+    }
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashFree()",
+                testStatus);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psHash02.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psHash02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psHash02.c	(revision 1553)
@@ -0,0 +1,94 @@
+/*****************************************************************************
+    This code will test whether hash tables entries can be inserted correctly,
+    and retrieved correctly.
+ 
+    NOTE: Add code to test whether duplicates are handled correctly (use a
+    small hash table and lots of keys).
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+int imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    p_psMemSetDeallocator(id,(psFreeFcn)IdFree);
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+int main()
+{
+    psHash *myHashTable = NULL;
+    int testStatus      = true;
+    int i               = 0;
+    ID *id = NULL;
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    int currentId = psMemGetId();
+    int memLeaks        = 0;
+
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashAdd()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], id);
+        psFree(id);
+        i++;
+    }
+
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (0 != strcmp(myData[i], id->name)) {
+            fprintf(stderr, "%s: Hash table entry for key %s was %s (should be %s).\n",
+                    __func__, myKeys[i], id->name, myData[i]);
+        }
+        i++;
+    }
+    id = psHashLookup(myHashTable, "BogusKey");
+    if (id != NULL) {
+        fprintf(stderr, "%s: Hash table entry for key %s was not NULL.\n",
+                __func__, "BogusKey");
+    }
+
+    //    psHashFree(myHashTable, NULL);
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashAdd()",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psHash03.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psHash03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psHash03.c	(revision 1553)
@@ -0,0 +1,139 @@
+/*****************************************************************************
+    This code will test whether hash tables entries can be removed correctly.
+ 
+    NOTE: Add code to test whether duplicates are handled correctly.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psHash.h"
+#include "psMemory.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+int imGlobal = 0;
+int currentId = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+// NOTE: This is my own little routine I used in debugging a memory
+// leak.  I will take this out of this file later.
+void printMemBlocks(char *myString)
+{
+    psMemBlock **memBlocks = NULL;
+    psMemBlock *tmp = NULL;
+    int numBlocks = 0;
+
+    numBlocks = psMemCheckLeaks(currentId, &memBlocks, NULL);
+    printf("******************** %s ********************\n", myString);
+    printf("%d mem blocks\n", psMemCheckLeaks(currentId,NULL,NULL));
+    printf("%d blocks\n", numBlocks);
+    printf("*  ");
+    if (memBlocks != NULL) {
+        for (tmp = *memBlocks; tmp != NULL; tmp = tmp->nextBlock) {
+            printf("%d ", (int) tmp->id);
+        }
+    }
+    printf("*\n");
+    printf("*************************************************\n");
+    psFree(memBlocks);
+}
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = NULL;
+
+    id = psAlloc(sizeof(ID));
+    p_psMemSetDeallocator(id,(psFreeFcn)IdFree);
+
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+int main()
+{
+    psHash *myHashTable = NULL;
+    int testStatus      = true;
+    int i               = 0;
+    int TotalKeys       = 0;
+    bool retVal         = false;
+    ID *id = NULL;
+    ID *ids[4];
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    int memLeaks        = 0;
+
+    currentId = psMemGetId();
+
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashRemove()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+
+    i = 0;
+    while (myKeys[i] != NULL) {
+        ids[i] = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], ids[i]);
+        i++;
+    }
+    TotalKeys = i - 1;
+
+    i = TotalKeys;
+    while (i >= 0) {
+
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (0 != strcmp(myData[i], id->name)) {
+            fprintf(stderr, "%s: Hash table entry for key %s was %s (should be %s).\n",
+                    __func__, myKeys[i], id->name, myData[i]);
+        }
+        i--;
+    }
+
+    i = 0;
+    while (myKeys[i] != NULL) {
+        // The psHashRemove() procedure removes the entry from the hash
+        // table and deletes the data.
+        retVal = psHashRemove(myHashTable, myKeys[i]);
+        if (!retVal) {
+            fprintf(stderr,"%s: Hash table entry not removed.\n",__func__);
+        }
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (id != NULL) {
+            fprintf(stderr, "%s: Hash table entry for key %s not removed.\n",
+                    __func__, "IDA");
+        }
+        i++;
+    }
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashRemove()",
+                testStatus);
+
+    psFree(myHashTable);
+    for(i=0; i<(TotalKeys+1); i++) {
+        psFree(ids[i]);
+    }
+    memLeaks = psMemCheckLeaks(currentId,NULL,stdout);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(true);
+
+    return (!testStatus);
+}
+
Index: /tags/rel2_1/psLib/test/collections/tst_psHash04.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psHash04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psHash04.c	(revision 1553)
@@ -0,0 +1,84 @@
+/*****************************************************************************
+    This code will test whether the call psHashKeyList() function works.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+int imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    p_psMemSetDeallocator(id,(psFreeFcn)IdFree);
+
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+int main()
+{
+    psHash *myHashTable = NULL;
+    int testStatus      = true;
+    int i               = 0;
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    int currentId = psMemGetId();
+    int memLeaks        = 0;
+    psList *myLinkList = NULL;
+    psListElem *tmp = NULL;
+    ID* id = NULL;
+
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashKeyList()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], id);
+        psFree(id);
+        i++;
+    }
+    myLinkList = psHashKeyList(myHashTable);
+    tmp = myLinkList->head;
+    while (tmp != NULL) {
+        printf("Linked List Entries: %s\n", (char *) tmp->data);
+        tmp = tmp->next;
+    }
+
+    psFree(myLinkList);
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashKeyList()",
+                testStatus);
+
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return(!testStatus);
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psList.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psList.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psList.c	(revision 1553)
@@ -0,0 +1,1154 @@
+/** @file  tst_psList.c
+ *
+ *  @brief Contains the tests for psList.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib.h"
+
+void printListInt(psList* list);
+
+
+static int testListAlloc(void);
+static int testListAdd(void);
+static int testListGet(void);
+static int testListRemove(void);
+static int testListConvert(void);
+static int testListIterator(void);
+static int testListFree(void);
+static int testListSort(void);
+
+testDescription tests[] = {
+                              {
+                                  testListAlloc,487,"psListAlloc",0,false
+                              },
+                              {
+                                  testListAdd,488,"psListAdd",0,false
+                              },
+                              {
+                                  testListGet,489,"psListGet",0,false
+                              },
+                              {
+                                  testListRemove,490,"psListRemove",0,false
+                              },
+                              {
+                                  testListConvert,491,"psListConvert",0,false
+                              },
+                              {
+                                  testListIterator,494,"psListIterator",0,false
+                              },
+                              {
+                                  testListFree,627,"psListFree",0,false
+                              },
+                              {
+                                  testListSort,624,"psListSort",0,false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if (! runTestSuite(stderr,"psList",tests,argc,argv) ) {
+        psError(__FILE__,"One or more tests failed");
+        return 1;
+    }
+    return 0;
+}
+
+int testListAlloc(void)
+{
+    psList* list;
+    int ref;
+    float* data;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psListAlloc shall create a psList with either 0 or 1 element.");
+
+    data = psAlloc(sizeof(float));
+
+    // if psListAlloc is invoked with a NULL parameter, it shall return an
+    // empty psList struct with head=tail=NULL and n=0. Otherwise, it shall
+    // return a psList of one element (head=tail=data, n=1).
+
+    list = psListAlloc(NULL);
+    if (list == NULL) {
+        psError(__func__,"psListAlloc failed to return a list.");
+        return 1;
+    }
+
+    if (list->head != NULL || list->tail != NULL) {
+        psError(__func__,"head and/or tail was not NULL for empty list.");
+        return 2;
+    }
+
+    if (list->size != 0) {
+        psError(__func__,"size of list wasn't zero for empty list.");
+        return 3;
+    }
+
+    psFree(list);
+
+    list = psListAlloc(data);
+    if (list == NULL) {
+        psError(__func__,"psListAlloc failed to return a list.");
+        return 4;
+    }
+
+    if (list->head == NULL || list->tail == NULL) {
+        psError(__func__,"head and/or tail was NULL for one-element new list.");
+        return 5;
+    }
+
+    if (list->head->data != data || list->tail->data != data) {
+        psError(__func__,"head and/or tail didn't point to data's node for one-element new list.");
+        return 6;
+    }
+
+    if (list->size != 1) {
+        psError(__func__,"size of list wasn't correctly set for new, one-element list.");
+        return 7;
+    }
+
+    ref = psMemGetRefCounter(data);
+    if (ref != 2) {
+        psError(__func__,"psList didn't increment reference count of data (%d.",ref);
+        return 8;
+    }
+
+
+    psFree(list);
+
+    psFree(data);
+
+    return 0;
+}
+
+int testListAdd(void)
+{
+    psList* list = NULL;
+    int* data = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psListAdd shall add an element to list");
+
+    /*
+        psListAdd(list,data,where) should be tested in the instance where:
+
+        1. list is NULL (error)
+        2. data is NULL (error, list should not grow)
+        3. where is PS_LIST_HEAD or PS_LIST_TAIL
+        4. where is not PS_LIST_* but <0
+        5. where is >0
+    */
+
+    data = psAlloc(sizeof(int));
+    *data = 1;
+
+    //  1. list is NULL (error)
+    if (psListAdd(NULL,data,PS_LIST_HEAD)) {
+        psError(__func__,"psListAdd was given a NULL list, but returned a true/success.");
+        return 1;
+    }
+
+    list = psListAlloc(data);
+    psFree(data);
+    if (list->size != 1) {
+        psError(__func__,"psListAlloc didn't create a list properly.");
+        return 2;
+    }
+
+    //  2. data is NULL (error, list should not grow)
+    if (psListAdd(list, NULL,PS_LIST_HEAD)) {
+        psError(__func__,"psListAdd successfully added a NULL data item?");
+        return 40;
+    }
+    if ( list->size != 1) {
+        psError(__func__,"psListAdd with a NULL data element changed the list size or returned success.");
+        return 3;
+    }
+
+    //  3. where is PS_LIST_HEAD or PS_LIST_TAIL
+    data = psAlloc(sizeof(int));
+    *data = 2;
+    if ( ! psListAdd(list,data,PS_LIST_HEAD) ) {
+        psError(__func__,"psListAdd failed to add a data item to head.");
+        return 21;
+    }
+
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 20;
+    }
+    psFree(data);
+
+    // verify that the size incremented
+    if (list->size != 2) {
+        psError(__func__,"psListAdd didn't increment the size by one");
+        return 4;
+    }
+
+    // verify that the head is the inserted data item
+    if (*(int*)list->head->data != 2) {
+        psError(__func__,"psListAdd with PS_LIST_HEAD didn't insert at the head.");
+        return 5;
+    }
+
+    data = psAlloc(sizeof(int));
+    *data = 3;
+    if ( ! psListAdd(list,data,PS_LIST_TAIL) ) {
+        psError(__func__,"psListAdd failed to add a data item to tail.");
+        return 21;
+    }
+
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 22;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->size != 3) {
+        psError(__func__,"psListAdd didn't increment the size by 1");
+        return 6;
+    }
+
+    // verify that the head is still the same
+    if (*(int*)list->head->data != 2) {
+        psError(__func__,"psListAdd with PS_LIST_TAIL modified the head.");
+        return 7;
+    }
+
+    // verify that the tail is the data item inserted
+    if (*(int*)list->tail->data != 3) {
+        psError(__func__,"psListAdd with PS_LIST_TAIL didn't insert at the tail.");
+        return 8;
+    }
+
+    // 4. where is not PS_LIST_* but <0
+
+    data = psAlloc(sizeof(int));
+    *data = 4;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error with invalid insert location");
+
+    if ( psListAdd(list,data,-10) ) {
+        psError(__func__,"psListAdd successfully added data to a -10 position?");
+        return 30;
+    }
+    if (psMemGetRefCounter(data) != 1) {
+        psError(__func__,"psListAdd incremented the data reference count.");
+        return 24;
+    }
+    psFree(data);
+    // verify that the size wasn't incremented
+    if (list->size != 3) {
+        printListInt(list);
+        psError(__func__,"psListAdd didn't insert to head when where was invalid.");
+        return 9;
+    }
+
+    // 5. where is >0
+    data = psAlloc(sizeof(int));
+    *data = 5;
+
+    if ( ! psListAdd(list,data,1) ) {
+        psError(__func__,"psListAdd failed to add data to 1 position.");
+        return 30;
+    }
+
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 25;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->size != 4 || *(int*)list->head->next->data != 5) {
+        printListInt(list);
+        psError(__func__,"psListAdd didn't insert to position #1.");
+        return 10;
+    }
+
+    data = psAlloc(sizeof(int));
+    *data = 6;
+    if ( ! psListAdd(list,data,3) ) {
+        psError(__func__,"psListAdd failed to add data to 4 position.");
+        return 31;
+    }
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 26;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->size != 5  || *(int *)list->head->next->next->next->data != 6) {
+        printListInt(list);
+        psError(__func__,"psListAdd didn't insert to position #4.");
+        return 50;
+    }
+
+    data = psAlloc(sizeof(int));
+    *data = 7;
+    if ( ! psListAdd(list,data,2) ) {
+        psError(__func__,"psListAdd failed to add data to 2 position.");
+        return 32;
+    }
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 28;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->size != 6  || *(int *)list->head->next->next->data != 7) {
+        printListInt(list);
+        psError(__func__,"psListAdd didn't insert to position #2.");
+        return 11;
+    }
+
+    data = psAlloc(sizeof(int));
+    *data = 7;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning.");
+
+    if ( ! psListAdd(list,data,9) ) {
+        psError(__func__,"psListAdd failed to add data to a 9 position?");
+        return 30;
+    }
+
+    if (psMemGetRefCounter(data) != 2) {
+        psError(__func__,"psListAdd didn't increment the data reference count.");
+        return 29;
+    }
+
+    psFree(data);
+
+    // verify that the size incremented
+    if (list->size != 7) {
+        printListInt(list);
+        psError(__func__,"psListAdd didn't insert to position #9.");
+        return 12;
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+void printListInt(psList* list)
+{
+    int* data = NULL;
+    bool first = true;
+
+    psListSetIterator(list,PS_LIST_HEAD);
+    data = psListGetCurrent(list);
+
+    while ( data != NULL ) {
+        if (!first) {
+            printf(", %d",*(int*)data);
+        } else {
+            printf("%d",*(int*)data);
+            first = false;
+        }
+        data = psListGetNext(list);
+    }
+
+    printf(".\n");
+}
+
+
+int testListGet(void)
+{
+    psList* list = NULL;
+    int* data;
+
+    /*
+     psListGet(list,which) shall be tested with the following instances
+
+        1. list is NULL.
+        2. which>0 and which<list.n.
+        3. which>list.n.
+        4. which=PS_LIST_HEAD
+        5. which=PS_LIST_NEXT
+        6. which=PS_LIST_TAIL
+        7. which=PS_LIST_PREV
+        8. which<0 and not any PS_LIST_* values
+    */
+
+    //  1. list is NULL.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if (psListGet(list,PS_LIST_HEAD) != NULL) {
+        psError(__func__,"psListGet didn't return NULL given a NULL list.");
+        return 1;
+    };
+
+    // create a list
+    data = psAlloc(sizeof(int));
+    *data = 0;
+    list = psListAlloc(data);
+    psFree(data);
+
+    data = psAlloc(sizeof(int));
+    *data = 1;
+    psListAdd(list,data,PS_LIST_TAIL);
+    psFree(data);
+
+    data = psAlloc(sizeof(int));
+    *data = 2;
+    psListAdd(list,data,PS_LIST_TAIL);
+    psFree(data);
+
+    data = psAlloc(sizeof(int));
+    *data = 3;
+    psListAdd(list,data,PS_LIST_TAIL);
+    psFree(data);
+
+    //  2. which>0 and which<list.n.
+    data = (int*)psListGet(list,3);
+    if (data == NULL || *data != 3) {
+        psError(__func__,"psListGet failed with which=3");
+        return 2;
+    }
+    data = (int*)psListGet(list,1);
+    if (data == NULL || *data != 1) {
+        psError(__func__,"psListGet failed with which=1");
+        return 3;
+    }
+
+    //  3. which>=list.n.
+    data = (int*)psListGet(list,5);
+    if (data != NULL) {
+        psError(__func__,"psListGet failed with which=5");
+        return 4;
+    }
+    data = (int*)psListGet(list,4);
+    if (data != NULL) {
+        psError(__func__,"psListGet failed with which=4");
+        return 5;
+    }
+
+    //  4. which=PS_LIST_HEAD
+    data = (int*)psListGet(list,PS_LIST_HEAD);
+    if (data == NULL || *data != 0) {
+        psError(__func__,"psListGet failed with which=PS_LIST_HEAD");
+        return 6;
+    }
+
+    //  5. which=PS_LIST_NEXT
+    data = (int*)psListGet(list,PS_LIST_NEXT);
+    if (data == NULL || *data != 1) {
+        psError(__func__,"psListGet failed with which=PS_LIST_NEXT");
+        return 7;
+    }
+
+    //  6. which=PS_LIST_TAIL
+    data = (int*)psListGet(list,PS_LIST_TAIL);
+    if (data == NULL || *data != 3) {
+        psError(__func__,"psListGet failed with which=PS_LIST_TAIL");
+        return 8;
+    }
+
+    //  7. which=PS_LIST_PREV
+    data = (int*)psListGet(list,PS_LIST_PREVIOUS);
+    if (data == NULL || *data != 2) {
+        psError(__func__,"psListGet failed with which=PS_LIST_PREV");
+        return 9;
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+int testListRemove(void)
+{
+    psList* list = NULL;
+    int* data;
+
+    /*
+        psListRemove(list,data,which) should be tested under the following conditions:
+
+        1. list is NULL
+        2. which is PS_LIST_HEAD (remove first element of list)
+        3. which is PS_LIST_TAIL (remove last element of list)
+        4. which is PS_LIST_NEXT (element right of cursor [which should be head,tail, and neither])
+        5. which is PS_LIST_PREV (element left of cursor [which should be head,tail, and neither])
+        6. which is PS_LIST_UNKNOWN and data=NULL (error)
+        7. which is PS_LIST_UNKNOWN and data=[head,tail,other list items]
+        8. which is PS_LIST_UNKNOWN and data!=NULL and data!=any element in list
+
+        In all conditions that are not an error, list.n shall be decremented and only the specified element
+        shall be removed. After each step, list.n should be checked to verify that it is the true
+        number of elements in list.
+    */
+
+    //  1. list is NULL.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if (psListRemove(list,NULL,PS_LIST_HEAD)) {
+        psError(__func__,"psListRemove didn't return false given a NULL list.");
+        return 1;
+    };
+
+    // create a list
+    list = psListAlloc(NULL);
+
+    for (int lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(int));
+        *data = lcv;
+        psListAdd(list,data,PS_LIST_TAIL);
+        psMemDecrRefCounter(data);
+    }
+
+
+    // 2. which is PS_LIST_HEAD (remove first element of list)
+    data = psListGet(list,PS_LIST_HEAD);
+    if ( (! psListRemove(list,NULL,PS_LIST_HEAD)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_HEAD");
+        return 1;
+    }
+
+    if (list->size != 14) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 14.");
+        return 1;
+    }
+
+    // 3. which is PS_LIST_TAIL (remove last element of list)
+    data = psListGet(list,PS_LIST_TAIL);
+    if ( (! psListRemove(list,NULL,PS_LIST_TAIL)) ||
+            (psListGet(list,PS_LIST_TAIL) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_TAIL");
+        return 1;
+    }
+
+    if (list->size != 13) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 13.");
+        return 1;
+    }
+
+    // 4. which is PS_LIST_NEXT (element right of cursor [which should be head,tail, and neither])
+    psListSetIterator(list,PS_LIST_HEAD);
+    if (! psListRemove(list,NULL,PS_LIST_NEXT)) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_NEXT @ PS_LIST_HEAD");
+        return 1;
+    }
+
+    if (list->size != 12) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 12.");
+        return 1;
+    }
+
+    psListSetIterator(list,PS_LIST_TAIL);
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    if (psListRemove(list,NULL,PS_LIST_NEXT)) {
+        printListInt(list);
+        psError(__func__,"Removed something with PS_LIST_NEXT @ PS_LIST_TAIL");
+        return 1;
+    }
+
+    data = psListGet(list,3);
+    psListSetIterator(list,2);
+    if ( (!psListRemove(list,NULL,PS_LIST_NEXT)) ||
+            ( psListGet(list,3) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_NEXT @ which=2");
+        return 1;
+    }
+
+    if (list->size != 11) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 11.");
+        return 1;
+    }
+
+    // 5. which is PS_LIST_PREV (element left of cursor [which should be head,tail, and neither])
+    psListSetIterator(list,PS_LIST_HEAD);
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    if (psListRemove(list,NULL,PS_LIST_PREVIOUS)) {
+        printListInt(list);
+        psError(__func__,"removed something for PS_LIST_PREVIOUS @ PS_LIST_HEAD");
+        return 1;
+    }
+
+    data = psListGet(list,9);
+    psListSetIterator(list,PS_LIST_TAIL);
+    if ( (!psListRemove(list,NULL,PS_LIST_PREVIOUS)) ||
+            (psListGet(list,9) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_PREVIOUS @ PS_LIST_TAIL");
+        return 1;
+    }
+
+    if (list->size != 10) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 10.");
+        return 1;
+    }
+
+    data = psListGet(list,1);
+    psListSetIterator(list,2);
+    if ( (!psListRemove(list,NULL,PS_LIST_PREVIOUS)) ||
+            ( psListGet(list,1) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_PREVIOUS @ which=2");
+        return 1;
+    }
+
+    if (list->size != 9) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 9.");
+        return 1;
+    }
+
+    // 6. which is PS_LIST_UNKNOWN and data=NULL (error)
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    if (psListRemove(list,NULL,PS_LIST_UNKNOWN)) {
+        printListInt(list);
+        psError(__func__,"removed something for PS_LIST_UNKNOWN with data=NULL");
+        return 1;
+    }
+
+    // 7. which is PS_LIST_UNKNOWN and data=[head,tail,other list items]
+    data = psListGet(list,PS_LIST_HEAD);
+    if ( (! psListRemove(list,data,PS_LIST_UNKNOWN)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_UNKNOWN @ PS_LIST_HEAD");
+        return 1;
+    }
+
+    if (list->size != 8) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 8.");
+        return 1;
+    }
+
+    data = psListGet(list,PS_LIST_TAIL);
+    if ( (!psListRemove(list,data,PS_LIST_UNKNOWN)) ||
+            (psListGet(list,PS_LIST_TAIL) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_UNKNOWN @ PS_LIST_TAIL");
+        return 1;
+    }
+
+    if (list->size != 7) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 7.");
+        return 1;
+    }
+
+    psListSetIterator(list,PS_LIST_HEAD);
+
+    data = psListGet(list,PS_LIST_NEXT);
+    if ( (! psListRemove(list,data,PS_LIST_UNKNOWN))||
+            (psListGet(list,1) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove PS_LIST_UNKNOWN @ which=1");
+        return 1;
+    }
+
+    if (list->size != 6) {
+        printListInt(list);
+        psError(__func__,"Didn't decrement size properly to 6.");
+        return 1;
+    }
+
+    // 8. which is PS_LIST_UNKNOWN and data!=NULL and data!=any element in list
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    if ( psListRemove(list,data,PS_LIST_UNKNOWN) ) {
+        printListInt(list);
+        psError(__func__,"removed something for PS_LIST_UNKNOWN with previously removed item");
+        return 1;
+    }
+
+    // clear out the list
+    psListRemove(list,NULL,PS_LIST_HEAD);
+    psListRemove(list,NULL,PS_LIST_HEAD);
+    psListRemove(list,NULL,PS_LIST_HEAD);
+    psListRemove(list,NULL,PS_LIST_HEAD);
+    psListRemove(list,NULL,PS_LIST_HEAD);
+
+    data = psListGet(list,PS_LIST_HEAD);
+    if ( (! psListRemove(list,data,PS_LIST_HEAD)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(__func__,"Failed to remove last element");
+        return 1;
+    }
+
+    if (list->size != 0) {
+        printListInt(list);
+        psError(__func__,"Didn't remove all the elements.");
+        return 1;
+    }
+
+    psFree(list);
+
+    return 0;
+
+}
+
+int testListConvert(void)
+{
+
+    psList* list = NULL;
+    psArray* arr = NULL;
+    int* data;
+
+    /*
+        array=psListToArray(list) shall take each element of the list, increment
+        their reference, and insert them into the returned fresh void* array.
+        The list shall not be changed, except for the element reference increment.
+    */
+
+    // test dlist -> array
+
+    // create a list
+    list = psListAlloc(NULL);
+    for (int lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(int));
+        *data = lcv;
+        psListAdd(list,data,PS_LIST_TAIL);
+        psMemDecrRefCounter(data);
+    }
+
+    arr = psListToArray(list);
+
+    if (arr->n != 15 || list->size != 15) {
+        psError(__func__,"The created array didn't have the proper size");
+        return 1;
+    }
+    for (int i=0;i<arr->n;i++) {
+        if (i != *(int*)arr->data[i]) {
+            psError(__func__,"Element %d of array is incorrect (%d).",
+                    i,*(int*)arr->data[i]);
+            return 1;
+        }
+        if (i != *(int*)psListGet(list,i)) {
+            psError(__func__,"Element %d of list is incorrect (%d).",
+                    i,*(int*)arr->data[i]);
+            return 1;
+        }
+        if (psMemGetRefCounter(arr->data[i]) != 2) {
+            psError(__func__,"Element %d had wrong reference count (%d).",
+                    i,psMemGetRefCounter(arr->data[i]));
+            return 1;
+        }
+    }
+
+    psFree(arr);
+    psFree(list);
+
+    // test array -> dlist
+
+    // create an array
+    arr = psArrayAlloc(15);
+    arr->n = arr->nalloc;
+    for (int lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(int));
+        *data = lcv;
+        arr->data[lcv] = data;
+    }
+
+    list = psArrayToList(arr);
+
+    if (arr->n != 15 || list->size != 15) {
+        psError(__func__,"The created array didn't have the proper size");
+        return 1;
+    }
+    for (int i=0;i<arr->n;i++) {
+        if (i != *(int*)arr->data[i]) {
+            psError(__func__,"Element %d of array is incorrect (%d).",
+                    i,*(int*)arr->data[i]);
+            return 1;
+        }
+        if (i != *(int*)psListGet(list,i)) {
+            psError(__func__,"Element %d of list is incorrect (%d).",
+                    i,*(int*)arr->data[i]);
+            return 1;
+        }
+        if (psMemGetRefCounter(arr->data[i]) != 2) {
+            psError(__func__,"Element %d had wrong reference count (%d).",
+                    i,psMemGetRefCounter(arr->data[i]));
+            return 1;
+        }
+    }
+
+    psFree(arr);
+    psFree(list);
+
+    // now, make sure if input array/list is NULL, output is NULL
+
+    arr = psListToArray(NULL);
+    if (arr != NULL) {
+        psError(__func__,"psListToArray didn't return NULL when given NULL");
+        return 1;
+    }
+
+    list = psArrayToList(NULL);
+    if (list != NULL) {
+        psError(__func__,"psArrayToList didn't return NULL when given NULL");
+        return 1;
+    }
+
+    // now, see what happens with a zero-size array/list
+    arr = psArrayAlloc(1);
+    arr->n = 0;
+    list = psArrayToList(arr);
+    if (list == NULL) {
+        psError(__func__,"psArrayToList didn't create an empty list from an "
+                "empty array.");
+        return 1;
+    }
+    psFree(arr);
+    psFree(list);
+
+    list = psListAlloc(NULL);
+    arr = psListToArray(list);
+    if (arr == NULL) {
+        psError(__func__,"psArrayToList didn't create an empty array from an "
+                "empty list.");
+        return 1;
+    }
+    psFree(arr);
+    psFree(list);
+
+    return 0;
+}
+
+int testListIterator(void)
+{
+    psList* list = NULL;
+    int* data;
+
+    psLogMsg(__func__,PS_LOG_INFO," psListSetIterator/psListGetNext/psListGetPrev"
+             " shall move the list cursor to the specified location");
+
+    /*
+            psDlistSetIterator(list,where) shall:
+
+            1. output error message and do nothing if list=NULL
+            2. set list.cursor to list.head if where=PS_LIST_HEAD
+            3. set list.cursor to list.tail if where=PS_LIST_TAIL
+            4. set list.cursor to list.cursor->next if where=PS_LIST_NEXT
+            5. set list.cursor to list.cursor->prev if where=PS_LIST_PREV
+            6. leave list.cursor untouched if where=PS_LIST_UNKNOWN or PS_LIST_CURRENT
+
+            psDlistGetNext(list) shall be functionally equivalent to
+            psDlistSetIterator(list,PS_LIST_NEXT) but returns list.cursor.
+
+            psDlistGetPrev(list) shall be functionally equivalent to
+            psDlistSetIterator(list,PS_LIST_PREV) but returns list.cursor.
+    */
+
+    // create a list
+    list = psListAlloc(NULL);
+    for (int lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(int));
+        *data = lcv;
+        psListAdd(list,data,PS_LIST_TAIL);
+        psFree(data);
+    }
+
+
+    // 1. output error message and do nothing if list=NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error with "
+             "'Unexpected null pointer'");
+    psListSetIterator(NULL,PS_LIST_HEAD);
+
+    // 3. set list.cursor to list.tail if where=PS_LIST_TAIL
+    psListSetIterator(list,PS_LIST_TAIL);
+    if (*(int*)psListGetCurrent(list) != 14) {
+        psError(__func__,"Didn't successfully move cursor to tail.");
+        return 1;
+    }
+
+    // 2. set list.cursor to list.head if where=PS_LIST_HEAD
+    psListSetIterator(list,PS_LIST_HEAD);
+    if (*(int*)psListGetCurrent(list) != 0) {
+        psError(__func__,"Didn't successfully move cursor to head.");
+        return 2;
+    }
+
+    // 4. set list.cursor to list.cursor->next if where=PS_LIST_NEXT
+    psListSetIterator(list,PS_LIST_NEXT);
+    if (*(int*)psListGetCurrent(list) != 1) {
+        psError(__func__,"Didn't successfully move cursor to next.");
+        return 3;
+    }
+    psListSetIterator(list,PS_LIST_NEXT);
+    if (*(int*)psListGetCurrent(list) != 2) {
+        psError(__func__,"Didn't successfully move cursor to next twice.");
+        return 4;
+    }
+
+    // 5. set list.cursor to list.cursor->prev if where=PS_LIST_PREV
+    psListSetIterator(list,PS_LIST_PREVIOUS);
+    if (*(int*)psListGetCurrent(list) != 1) {
+        psError(__func__,"Didn't successfully move cursor to previous.");
+        return 5;
+    }
+    psListSetIterator(list,PS_LIST_PREVIOUS);
+    if (*(int*)psListGetCurrent(list) != 0) {
+        psError(__func__,"Didn't successfully move cursor to previous twice.");
+        return 6;
+    }
+
+    // 6. leave list.cursor untouched if where=PS_LIST_UNKNOWN or PS_LIST_CURRENT
+    psListSetIterator(list,PS_LIST_NEXT);   // move off of head (works according to above)
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error with 'Can't move to an unknown position.'");
+    psListSetIterator(list,PS_LIST_UNKNOWN);
+    if (*(int*)psListGetCurrent(list) != 1) {
+        psError(__func__,"PS_LIST_UNKNOWN moved cursor.");
+        return 7;
+    }
+    psListSetIterator(list,PS_LIST_CURRENT);
+    if (*(int*)psListGetCurrent(list) != 1) {
+        psError(__func__,"PS_LIST_CURRENT moved cursor.");
+        return 8;
+    }
+
+    // test psListGetPrevious/Next
+    if (*(int*)psListGetNext(list) != 2) {
+        psError(__func__,"psListGetNext didn't move cursor to next.");
+        return 9;
+    }
+    if (*(int*)psListGetNext(list) != 3) {
+        psError(__func__,"psListGetNext didn't move cursor to next.");
+        return 10;
+    }
+    if (*(int*)psListGetPrevious(list) != 2) {
+        psError(__func__,"psListGetPrevious didn't move cursor to previous.");
+        return 11;
+    }
+    if (*(int*)psListGetPrevious(list) != 1) {
+        psError(__func__,"psListGetPrevious didn't move cursor to previous.");
+        return 12;
+    }
+    if (*(int*)psListGetPrevious(list) != 0) {
+        psError(__func__,"psListGetPrevious didn't move cursor to previous..");
+        return 13;
+    }
+    if (psListGetPrevious(list) != NULL) {
+        psError(__func__,"psListGetPrevious moved cursor beyond head.");
+        return 14;
+    }
+
+    psListSetIterator(list,PS_LIST_TAIL); // works according to an above test
+    if (psListGetNext(list) != NULL) {
+        psError(__func__,"psListGetNext moved cursor beyond tail.");
+        return 15;
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+int testListFree(void)
+{
+    float* data[15];
+    psList* list;
+
+    /*
+    Call psDlistAlloc to create a doubly linked list.
+
+    Create several data items and add them to the list.
+
+    Verify the data item's reference counter are incremented after adding to the list.
+    (not really needed, as psListAdd is tested elsewhere)
+    */
+
+    list = psListAlloc(NULL);
+    for (int lcv=0;lcv<15;lcv++) {
+        data[lcv] = psAlloc(sizeof(int));
+        *data[lcv] = lcv;
+        psListAdd(list,data[lcv],PS_LIST_TAIL);
+        if (psMemGetRefCounter(data[lcv]) != 2) {
+            psError(__func__,"Reference counter for data was not incremented");
+            return 1;
+        }
+    }
+
+    /*
+    Verify items are within the list.
+    (not needed, as psListAdd is tested elsewhere, but check anyway.)
+    */
+    if (list->size != 15) {
+        psError(__func__,"List wasn't populated as expected?");
+        return 2;
+    }
+
+    /*
+    Call psDlistFree with NULL specified as the elemFree function.
+    */
+
+    psFree(list);
+
+    /*
+    Verify the list is deallocated but not the data items.
+    (accomplished by checking for memory leaks)
+
+    Verify the data item's reference counters are decremented by one compared to when added to the list.
+    (technically, this could be accomplished by checking memory leaks too, but I checked anyway)
+    */
+
+    for (int i=0;i<15;i++) {
+        if (psMemGetRefCounter(data[i]) != 1) {
+            psError(__func__,"pslistFree didn't decrement the data item's reference counter");
+            return 3;
+        }
+        psFree(data[i]);
+    }
+
+    return 0;
+}
+
+int testListSort(void)
+{
+    psList* list;
+
+    list = psListAlloc(NULL);
+
+    for (int lcv=0;lcv<15;lcv++) {
+        float* data = psAlloc(sizeof(int));
+        if (lcv < 7) {
+            *data = 13-lcv*2;
+        } else {
+            *data = lcv*2-12;
+        }
+        psListAdd(list,data,PS_LIST_TAIL);
+        psFree(data);
+
+    }
+
+    printf("original list = [");
+    for (float* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %.1f",*iter);
+    }
+    printf(" ]\n");
+
+    list = psListSort(list,psCompareF32Ptr);
+
+    printf("sorted list = [");
+    for (float* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %.1f",*iter);
+    }
+    printf(" ]\n");
+
+    float* prevValue = psListGet(list,PS_LIST_HEAD);
+    for (float* iter = psListGet(list,PS_LIST_NEXT);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        if (*prevValue > *iter) {
+            psError(__func__,"Hey, the list wasn't sorted!?");
+            return 1;
+        }
+    }
+
+    list = psListSort(list,psCompareDescendingF32Ptr);
+
+    printf("descending sort list = [");
+    for (float* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %.1f",*iter);
+    }
+    printf(" ]\n");
+
+    prevValue = psListGet(list,PS_LIST_HEAD);
+    for (float* iter = psListGet(list,PS_LIST_NEXT);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        if (*prevValue < *iter) {
+            psError(__func__,"Hey, the list wasn't sorted!?");
+            return 1;
+        }
+    }
+
+    psFree(list);
+
+    /********** OK, now do the same thing with ints. *************/
+
+    list = psListAlloc(NULL);
+
+    for (int lcv=0;lcv<15;lcv++) {
+        psU32* data = psAlloc(sizeof(int));
+        if (lcv < 7) {
+            *data = 13-lcv*2;
+        } else {
+            *data = lcv*2-12;
+        }
+        psListAdd(list,data,PS_LIST_TAIL);
+        psFree(data);
+
+    }
+
+    printf("original list = [");
+    for (psU32* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %d",*iter);
+    }
+    printf(" ]\n");
+
+    list = psListSort(list,psCompareU32Ptr);
+
+    printf("sorted list = [");
+    for (psU32* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %d",*iter);
+    }
+    printf(" ]\n");
+
+    psU32* prev = psListGet(list,PS_LIST_HEAD);
+    for (psU32* iter = psListGet(list,PS_LIST_NEXT);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        if (*prev > *iter) {
+            psError(__func__,"Hey, the list wasn't sorted!?");
+            return 1;
+        }
+    }
+
+    list = psListSort(list,psCompareDescendingU32Ptr);
+
+    printf("descending sort list = [");
+    for (psU32* iter = psListGet(list,PS_LIST_HEAD);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        printf(" %d",*iter);
+    }
+    printf(" ]\n");
+
+    prev = psListGet(list,PS_LIST_HEAD);
+    for (psU32* iter = psListGet(list,PS_LIST_NEXT);
+            iter != NULL;
+            iter = psListGet(list,PS_LIST_NEXT)) {
+        if (*prev < *iter) {
+            psError(__func__,"Hey, the list wasn't sorted!?");
+            return 1;
+        }
+    }
+
+    psFree(list);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_01.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_01.c	(revision 1553)
@@ -0,0 +1,259 @@
+/** @file  tst_psMetadata_01.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Read 1st hdr from simple FITS file
+*     Test B - Read 2nd hdr from complex FITS file
+*     Test C - Read named hdr from complex FITS file
+*     Test D - Remove items with same name from all metadata
+*     Test E- Attempt to use null file descriptor
+*     Test F - Attempt to use two null inputs
+*     Test G - Attempt to use bad extNum/
+*     Test H - Attempt to use bad extNameTest
+*     Test I - Free psMetadataData
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-12 01:08:39 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
+
+static void printMetadataItemList(psList *metadataItemList)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListSetIterator(metadataItemList, PS_LIST_HEAD);
+    entryChild = psListGetCurrent(metadataItemList);
+    while (entryChild != NULL) {
+        printMetadataItem(entryChild, "    ");
+        entryChild = psListGetNext(metadataItemList);
+    }
+}
+
+static void printMetadataList(psList *metadataItemList)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListSetIterator(metadataItemList, PS_LIST_HEAD);
+    entryChild = psListGetCurrent(metadataItemList);
+    while (entryChild != NULL) {
+        printMetadataItem(entryChild, " ");
+        entryChild = psListGetNext(metadataItemList);
+    }
+}
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
+{
+    printf("%sKey Name: %8s  ", spaces, metadataItem->name);
+    printf("Key Type: %2d  ", metadataItem->type);
+
+    switch (metadataItem->type ) {
+    case PS_META_ITEM_SET:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+
+    if(metadataItem->items->size) {
+        printMetadataItemList(metadataItem->items);
+    }
+}
+
+static void printMetadataTable(psHash *mdTable)
+{
+    int i;
+    psHashBucket* ptr = NULL;
+    for(i=0; i<mdTable->nbucket; i++) {
+        ptr = mdTable->buckets[i];
+        while (ptr != NULL) {
+            printMetadataItem(ptr->data, " ");
+            ptr = ptr->next;
+        }
+    }
+}
+
+static void printMetadata(psMetadata *metadata)
+{
+    printf("Contents of metadata list:\n");
+    printMetadataList(metadata->list);
+    printf("\nContents of metadata table:\n");
+    printMetadataTable(metadata->table);
+}
+
+
+int main(int argc, char* argv[])
+{
+    int status = 0;
+    char fitsErr[ 256 ];
+    psMetadata *metadata1 = NULL;
+    psMetadata *metadata2 = NULL;
+    psMetadata *metadata3 = NULL;
+    fitsfile *fptr;
+
+
+    // Test A - Read 1st hdr from simple FITS file
+
+    /* Header contents for header_1.fits:
+
+        SIMPLE  =                    T / file does conform to FITS standard
+        BITPIX  =                    8 / number of bits per data pixel
+        NAXIS   =                    0 / number of data axes
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T11:11:18
+        END
+    */
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file");
+    fits_open_file(&fptr, "header_1.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata1 = psMetadataFReadHeader(metadata1, NULL, 1, fptr);
+    printMetadata(metadata1);
+    printFooter(stdout, "psMetadata", "Test A - Read 1st hdr from simple FITS file", true);
+
+
+    // Test B - Test B - Read 2nd hdr from complex FITS file
+
+    /* Header contents for header_2.fits:
+
+        SIMPLE  =                    T / file does conform to FITS standard
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        EXTEND  =                    T / FITS dataset may contain extensions
+        COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy
+        COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H
+        END
+        <DATA>
+
+        XTENSION= 'IMAGE   '           / IMAGE extension
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        PCOUNT  =                    0 / required keyword; must = 0
+        GCOUNT  =                    1 / required keyword; must = 1
+        BITPIX  =                  -64 / number of bits per data pixel
+        EXTNAME = 'MY_DATA_1'
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:14:45
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:15:29
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:18
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:46
+        END
+        <DATA>
+
+        XTENSION= 'IMAGE   '           / IMAGE extension
+        BITPIX  =                  -64 / number of bits per data pixel
+        NAXIS   =                    1 / number of data axes
+        NAXIS1  =                   64 / length of data axis 1
+        PCOUNT  =                    0 / required keyword; must = 0
+        GCOUNT  =                    1 / required keyword; must = 1
+        EXTNAME = 'MY_DATA_2'
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:12
+        HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:52
+        END
+        <DATA>
+    */
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file");
+    fits_open_file(&fptr, "header_2.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata2 = psMetadataFReadHeader(metadata2, NULL, 2, fptr);
+    printMetadata(metadata2);
+    printFooter(stdout, "psMetadata", "Test B - Read 2nd hdr from complex FITS file", true);
+
+
+    // Test C - Read named hdr from complex FITS file
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file");
+    fits_open_file(&fptr, "header_2.fits", READONLY, &status);
+    fits_get_errstatus( status, fitsErr );
+    status = 0;
+    printf("FITS file open status: %s\n\n",fitsErr);
+    metadata3 = psMetadataFReadHeader(metadata3, "MY_DATA_2", 0, fptr);
+    printMetadata(metadata3);
+    printFooter(stdout, "psMetadata", "Test C - Read named hdr from complex FITS file", true);
+
+
+    // Test D - Remove items with same name from all metadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Remove items with same name from all metadata");
+    printf("Removed HISTORY from all metadata from prior test. Resulting metadata:\n\n");
+    psMetadataRemove(metadata3, 0, "HISTORY");
+    printMetadata(metadata3);
+    printFooter(stdout, "psMetadata", "Test D - Remove items with same name from all metadata", true);
+
+
+    // Test E - Attempt to use null file descriptor
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to use null file descriptor",
+                            "Null FITS file descriptor not allowed", 0);
+    psMetadataFReadHeader(NULL, NULL, 1, NULL);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to use null file descriptor", true);
+
+
+    // Test F - Attempt to use two null inputs
+    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to use two null inputs",
+                            "Null extName and extNum = 0 not allowed", 0);
+    psMetadataFReadHeader(NULL, NULL, 0, fptr);
+    printFooter(stdout, "psMetadata", "Test F - Attempt to use two null inputs", true);
+
+
+    // Test G - Attempt to use bad extNum
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use bad extNum",
+                            "FITS error while locating header 22: tried to move past end of file", 0);
+    psMetadataFReadHeader(metadata1, NULL, 22, fptr);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use bad extNum", true);
+
+
+    // Test H - Attempt to use bad extName
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use bad extName",
+                            "FITS error while locating header AARGH: illegal HDU number", 0);
+    psMetadataFReadHeader(metadata1, "AARGH", 0, fptr);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to use bad extName", true);
+
+
+    // Test I- Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test I - Free psMetadata");
+    psFree(metadata1);
+    psFree(metadata2);
+    psFree(metadata3);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test I - Free psMetadata", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_02.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_02.c	(revision 1553)
@@ -0,0 +1,140 @@
+/** @file  tst_psMetadata_02.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata items
+*     Test B - Attempt to create metadata item with null name
+*     Test C - Attempt to create metadata item with invalid type
+*     Test D - Allocate metadata
+*     Test E - Attempt to add metadata item to null metadata
+*     Test F - Attempt to add null metadata item to metadata
+*     Test G - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:49:50 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadata *metadata = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item5 = NULL;
+    psMetadataItem *badItem = NULL;
+
+
+    // Test A - Allocate metadata items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 111);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_F32, "I am a single precision floating point", 222.222);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_F64, "I am a double precision floating point", 333.333);
+    item5 = psMetadataItemAlloc("myItem5", PS_META_STR, "I am a string", "HELLO WORLD");
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printMetadataItem(item5);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Attempt to create metadata item with null name
+    printNegativeTestHeader(stdout,"psMetadata", "Test B - Attempt to create metadata item with null name",
+                            "Null value for name not allowed", 0);
+    psMetadataItemAlloc(NULL, PS_META_STR, "I am a string", "HELLO WORLD");
+    printFooter(stdout, "psMetadata", "Test B - Attempt to create metadata item with null name", true);
+
+
+    // Test C - Attempt to create metadata item with invalid type
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to create metadata item with invalid type",
+                            "Invalid psMetadataType: 6", 0);
+    badItem = psMetadataItemAlloc("badItem", PS_META_IMG, "I am bad", "Bad comment");
+    printFooter(stdout, "psMetadata", "Test C - Attempt to create metadata item with invalid type", true);
+
+
+    // Test D - Allocate metadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Allocate metadata");
+    metadata = psMetadataAlloc();
+    printFooter(stdout, "psMetadata", "Test D - Allocate metadata", true);
+
+
+    // Test E - Attempt add metadata item to null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to add metadata item to null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataAddItem(NULL, PS_LIST_HEAD, item1);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to add metadata item to null metadata", true);
+
+
+    // Test F - Attempt add null metadata item to metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to add null metadata item to metadata",
+                            "Null metadata item not allowed", 0);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, NULL);
+    printFooter(stdout, "psMetadata", "Test F - Attempt to add null metadata item to metadata", true);
+
+
+    // Test G - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Free psMetadata");
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(item5);
+    psFree(badItem);
+    psFree(metadata);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test G - Free psMetadata", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_03.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_03.c	(revision 1553)
@@ -0,0 +1,141 @@
+/** @file  tst_psMetadata_03.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Remove items from metadata by name
+*     Test C - Remove items from metadata by index
+*     Test D - Attempt to use null metadata
+*     Test E - Attempt to remove non-existant metadata item by name
+*     Test F - Attempt to remove non-existant metadata item by index
+*     Test G - Free psMetadata
+ *
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-09 20:20:02 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Remove items from metadata by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataRemove(metadata, 0, "myItem1" );
+    psMetadataRemove(metadata, 0, "myItem2" );
+    printFooter(stdout, "psMetadata", "Test B - Remove items from metadata by name", true);
+
+
+    // Test C - Remove items from metadata by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    psMetadataRemove(metadata, 0, NULL);
+    psMetadataRemove(metadata, 0, NULL );
+    printFooter(stdout, "psMetadata", "Test C - Remove items from metadata by index", true);
+
+
+    // Test D - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataRemove(NULL, 0, NULL);
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null metadata", true);
+
+
+    // Test E - Attempt to remove non-existant metadata item by name
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by name",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    psMetadataRemove(metadata, 0, "AARGH");
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by name", true);
+
+
+    // Test F - Attempt to remove non-existant metadata item by index
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by index",
+                            "Couldn't find metadata item in list. Index: 22", 0);
+    psMetadataRemove(metadata, 22, NULL);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by index", true);
+
+
+    // Test G - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test G - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_04.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_04.c	(revision 1553)
@@ -0,0 +1,165 @@
+
+/** @file  tst_psMetadata_04.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Lookup metadata item by name
+*     Test C - Attempt to use null metadata
+*     Test D - Attempt to use null key
+*     Test E - Attempt to lookup non-existant metadata item
+*     Test F - Lookup metadata item by index
+*     Test G - Attempt to use null metadata
+*     Test H - Attempt to get non-existant metadata item
+*     Test I - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:50:57 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Lookup metadata item by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Lookup metadata item by name");
+    item = psMetadataLookup(metadata, "myItem2");
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    }
+    printFooter(stdout, "psMetadata", "Test B - Lookup metadata item by name", true);
+
+
+    // Test C - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataLookup(NULL, "myItem2");
+    printFooter(stdout, "psMetadata", "Test C - Attempt to use null metadata", true);
+
+
+    // Test D - Attempt to use null key
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null key",
+                            "Null key name not allowed", 0);
+    psMetadataLookup(metadata, NULL);
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null key", true);
+
+
+    // Test E - Attempt to lookup non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to lookup non-existant metadata item",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    psMetadataLookup(metadata, "AARGH");
+    printFooter(stdout, "psMetadata", "Test E - Attempt to lookup non-existant metadata item", true);
+
+
+    // Test F - Lookup metadata item by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Lookup metadata item by index");
+    item = psMetadataGet(metadata, 0);
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    }
+    printFooter(stdout, "psMetadata", "Test F - Lookup metadata item by index", true);
+
+
+    // Test G - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    item = psMetadataGet(NULL, 0);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata", true);
+
+
+    // Test H - Attempt to get non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to get non-existant metadata item",
+                            "Couldn't find metadata item with given index. Index: 22", 0);
+    psMetadataGet(metadata, 22);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to get non-existant metadata item", true);
+
+
+    // Test I - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test I - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test I - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_05.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_05.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_05.c	(revision 1553)
@@ -0,0 +1,207 @@
+
+
+/** @file  tst_psMetadata_05.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test I - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 01:39:37 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    long data;
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item = NULL;
+    psMetadata *metadata = NULL;
+    FILE *fd = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item3);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Set iterator at second index
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Set iterator at second index");
+    psMetadataSetIterator(metadata, 2);
+    printFooter(stdout, "psMetadata", "Test B - Set iterator at second index", true);
+
+
+    // Test C - Get next item at index
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Get next item at index");
+    item = psMetadataGetNext(metadata, NULL, 2);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test C - Get next item at index", true);
+
+
+    // Test D - Get next item at index and string
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Get next item at index and string");
+    item = psMetadataGetNext(metadata, "myItem1", 1);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test D - Get next item at index and string", true);
+
+
+    // Test E - Get previous item at index
+    printPositiveTestHeader(stdout, "psMetadata", "Test E - Get previous item at index");
+    item = psMetadataGetPrevious(metadata, NULL, 1);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+    } else {
+        printf("Found item named %s\n", item->name);
+    }
+    printFooter(stdout, "psMetadata", "Test E - Get previous item at index", true);
+
+
+    // Test F - Write metadata item to file
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Write metadata item to file");
+    fd = fopen("./tst_psMetadata05_OUT", "w");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for writing\n");
+    }
+    psMetadataItemPrint(fd, "%ld", item2);
+    printFooter(stdout, "psMetadata", "Test F - Write metadata item to file", true);
+    fclose(fd);
+    fd = fopen("./tst_psMetadata05_OUT", "r");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for reading\n");
+    }
+    fscanf(fd, "%ld", &data);
+    fclose(fd);
+    if(data != 55) {
+        printf("ERROR: Data in file is not as expected. Value: %ld. Should be: 55.\n", data);
+    }
+
+
+    // Test G - Attempt to use null metadata with setIterator
+    printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata with setIterator",
+                            "Null metadata collection not allowed", 0);
+    psMetadataSetIterator(NULL, 0);
+    printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata with setIterator", true);
+
+
+    // Test H - Attempt to use null metadata with getNext
+    printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use null metadata with getNext",
+                            "Null metadata collection not allowed", 0);
+    psMetadataGetNext(NULL, "myItem2", 0);
+    printFooter(stdout, "psMetadata", "Test H - Attempt to use null metadata with getNext", true);
+
+
+    // Test I - Attempt to use null metadata with getPrevious
+    printNegativeTestHeader(stdout,"psMetadata", "Test I - Attempt to use null metadata with getPrevious",
+                            "Null metadata collection not allowed", 0);
+    psMetadataGetPrevious(NULL, "myItem2", 0);
+    printFooter(stdout, "psMetadata", "Test I - Attempt to use null metadata with getPrevious", true);
+
+
+    // Test J - Attempt to use null file with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test J - Attempt to use null file with itemPrint",
+                            "Null file descriptor not allowed", 0);
+    psMetadataItemPrint(NULL, "Item value: %ld", item2);
+    printFooter(stdout, "psMetadata", "Test J - Attempt to use null file with itemPrint", true);
+
+
+    // Test K - Attempt to use null format with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test K - Attempt to use null format with itemPrint",
+                            "Null format not allowed", 0);
+    psMetadataItemPrint(fd, NULL, item2);
+    printFooter(stdout, "psMetadata", "Test K - Attempt to use null format with itemPrint", true);
+
+
+    // Test L - Attempt to use null item with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test L - Attempt to use null item with itemPrint",
+                            "Null metadata not allowed", 0);
+    psMetadataItemPrint(fd, "Item value: %ld", NULL);
+    printFooter(stdout, "psMetadata", "Test L - Attempt to use null item with itemPrint", true);
+
+
+    // Test M - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test M - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test M - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psMetadata_06.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psMetadata_06.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psMetadata_06.c	(revision 1553)
@@ -0,0 +1,125 @@
+
+/** @file  tst_psMetadata_06.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Add leaf node on top of existing leaf node
+*     Test C - Add leaf node to existing folder node
+*     Test D - Add folder node on top of existing leaf node
+*     Test E - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-10 23:22:24 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+#include <string.h>
+
+static void printMetadataItem(psMetadataItem *item)
+{
+    printf("Key Name: %8s  ", item->name);
+    printf("Key Type: %2d  ", item->type);
+
+    switch (item->type ) {
+    case PS_META_BOOL:
+        printf("Key Value: %15d  ", item->data.B);
+        break;
+    case PS_META_S32:
+        printf("Key Value: %15d  ", item->data.S32);
+        break;
+    case PS_META_F32:
+        printf("Key Value: %15.3f  ", item->data.F32);
+        break;
+    case PS_META_F64:
+        printf("Key Value: %15.3f  ", item->data.F64);
+        break;
+    case PS_META_STR:
+        printf("Key Value: %15s  ", (char*)item->data.V);
+        break;
+    case PS_META_IMG:
+    case PS_META_JPEG:
+    case PS_META_PNG:
+    case PS_META_ASTROM:
+    case PS_META_UNKNOWN:
+        printf("Value: unknown ");
+        break;
+    default:
+        printf("Bad type: %d ", item->type);
+    }
+    printf("Key Comment: %s\n", item->comment);
+}
+
+
+int main( int argc, char* argv[] )
+{
+    psMetadataItem *item1a = NULL;
+    psMetadataItem *item1b = NULL;
+    psMetadataItem *item1c = NULL;
+    psMetadataItem *item2a = NULL;
+    psMetadataItem *item2b = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata and items");
+    item1a = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
+    item1b = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 111);
+    item1c = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 222);
+    item2a = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 333);
+    item2b = psMetadataItemAlloc("myItem2", PS_META_ITEM_SET, "I am a folder node", NULL);
+    metadata = psMetadataAlloc();
+    printMetadataItem(item1a);
+    printMetadataItem(item1b);
+    printMetadataItem(item1c);
+    printMetadataItem(item2a);
+    printMetadataItem(item2b);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata and items", true);
+
+
+    // Test B - Add leaf node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1a);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1b);
+    printFooter(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node", true);
+
+
+    // Test C - Add leaf node to existing folder node
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Add leaf node to existing folder node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item1c);
+    printFooter(stdout, "psMetadata", "Test C - Add leaf node to existing folder node", true);
+
+
+    // Test D - Add folder node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node");
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2a);
+    psMetadataAddItem(metadata, PS_LIST_HEAD, item2b);
+    printFooter(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node", true);
+
+
+    // Test E - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test E - Free psMetadata");
+    psFree(item1a);
+    psFree(item1b);
+    psFree(item1c);
+    psFree(item2a);
+    psFree(item2b);
+    psFree(metadata);
+    psMemCheckLeaks(0, NULL, stdout);
+    psMemCheckCorruption(0);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test E - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psVector.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psVector.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psVector.c	(revision 1553)
@@ -0,0 +1,110 @@
+/** @file  tst_psVector.c
+ *
+ *  @brief Test driver for psVector integer functions
+ *
+ *  This test driver contains the following tests for psVector test point 1:
+ *     A)  Create S32 vector
+ *     B)  Add data to S32 vector
+ *     C)  Reallocate S32 vector bigger
+ *     D)  Reallocate S32 vector smaller
+ *     E)  Free S32 vector
+ *     F)  Attempt to create a S32 vector with zero size
+ *     G)  Attempt to realloc a null S32 vector
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+
+
+    // Test A - Create S32 vector
+    printPositiveTestHeader(stdout,"psVector", "Create S32 vector");
+    psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+    printf("Vector size = %d\n", psVec->nalloc);
+    printf("Vector type = %d\n", psVec->type.type);
+    printf("Vector dimen = %d\n", psVec->type.dimen);
+    printFooter(stdout, "psVector", "Create S32 vector", true);
+
+
+    // Test B - Add data to integer vector
+    printPositiveTestHeader(stdout, "psVector", "Add data to S32 vector");
+    for(int i = 0; i < 5; i++) {
+        psVec->data.S32[i] = i*10;
+        printf("Elem %d = %d\n", i, psVec->data.S32[i]);
+    }
+    printf("Vector size = %d\n", psVec->nalloc);
+    printf("Vector population = %d\n", psVec->n);
+    printFooter(stdout, "psVector", "Add data to S32 vector", true);
+
+
+    // Test C - Reallocate S32 vector bigger
+    printPositiveTestHeader(stdout,"psVector", "Reallocate S32 vector bigger");
+    psVec = psVectorRealloc(10, psVec);
+    printf("Adding more elements to S32 vector...\n");
+    for(int i = 5; i < 10; i++) {
+        psVec->data.S32[i] = i*10;
+        psVec->n++;
+        printf("Elem %d = %d\n", i, psVec->data.S32[i]);
+    }
+    printf("Vector size = %d\n", psVec->nalloc);
+    printf("Vector population = %d\n", psVec->n);
+    printFooter(stdout, "psVector", "Reallocate S32 vector bigger", true);
+
+
+    // Test D - Reallocate S32 vector smaller
+    printPositiveTestHeader(stdout,"psVector","Reallocate S32 vector smaller");
+    psVec = psVectorRealloc(3, psVec);
+    printf("Vector size = %d\n", psVec->nalloc);
+    for(int i = 0; i < 3; i++) {
+        printf("Elem %d = %d\n", i, psVec->data.S32[i]);
+    }
+    printf("Vector size = %d\n", psVec->nalloc);
+    printf("Vector population = %d\n", psVec->n);
+    printFooter(stdout, "psVector", "Reallocate integer S32 smaller", true);
+
+
+    // Test E - Free S32 vector
+    printPositiveTestHeader(stdout, "psVector", "Free S32 vector");
+    psFree(psVec);
+    int leaks = psMemCheckLeaks(0, NULL, stdout);
+    if(leaks != 0) {
+        printf("ERROR: Found %d memory leaks\n",leaks);
+    }
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psVector" ,"Free S32 vector", true);
+
+
+    // Test F - Attempt to create a S32 vector with zero size
+    printNegativeTestHeader(stdout,"psVector", "Attempt to create a S32 vector with zero size",
+                            "Invalid value for nalloc", 0);
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error message.");
+    psVector *vecBad = psVectorAlloc(0, PS_TYPE_S32);
+    if(vecBad != NULL) {
+        printf("ERROR: Return is not NULL\n");
+    }
+    printFooter(stdout, "psVector", "Attempt to create a S32 vector with zero size", true);
+
+
+    // Test G - Attempt to realloc a null S32 vector
+    printNegativeTestHeader(stdout,"psVector", "Attempt to realloc a null S32 vector",
+                            "Null input vector", 0);
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error message.");
+    psVectorRealloc(6, NULL);
+    printFooter(stdout, "psVector", "Attempt to realloc a null S32 vector", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psVectorSort_01.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psVectorSort_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psVectorSort_01.c	(revision 1553)
@@ -0,0 +1,83 @@
+/** @file  tst_psVectorSort_01.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This test driver contains the following tests for psVectorSort test point 1:
+ *     A)  Create float vectors
+ *     B)  Sort input float vector and put results into output float vector
+ *     C)  Free float vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    psVector *in = NULL;
+    psVector *out = NULL;
+    psVector *tempVec = NULL;
+
+
+    // Test A - Create float vectors
+    printPositiveTestHeader(stdout,"psVectorSort", "Create float vectors");
+    in = psVectorAlloc(7, PS_TYPE_F32);
+    in->n = 7;
+    out = psVectorAlloc(7, PS_TYPE_F32);
+    out->n = 7;
+    in->data.F32[0] = 7.0f;
+    in->data.F32[1] = 9.0f;
+    in->data.F32[2] = 3.0f;
+    in->data.F32[3] = 1.0f;
+    in->data.F32[4] = 5.0f;
+    in->data.F32[5] = 5.0f;
+    in->data.F32[6] = -20.0f;
+    for(int i=0; i<7; i++) {
+        printf("vec[%d] = %f\n", i, in->data.F32[i]);
+    }
+    printFooter(stdout, "psVectorSort", "Create float vectors", true);
+
+
+    // Test B - Sort input float vector and put results into output float vector
+    printPositiveTestHeader(stdout,"psVectorSort", "Sort float vector");
+    tempVec = out;
+    out = psVectorSort(out, in);
+    for(int i=0; i<7; i++) {
+        printf("vec[%d] = %f\n", i, out->data.F32[i]);
+    }
+    if(out != tempVec) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    printFooter(stdout, "psVectorSort", "Sort float vector", true);
+
+
+    // Test C - Sort input float vector into itself
+    printPositiveTestHeader(stdout,"psVectorSort", "Sort input float vector into itself");
+    in = psVectorSort(in, in);
+    for(int i=0; i<7; i++) {
+        printf("vec[%d] = %f\n", i, out->data.F32[i]);
+    }
+    printFooter(stdout, "psVectorSort", "Sort input float vector into itself", true);
+
+
+    // Test D - Free float vectors
+    printPositiveTestHeader(stdout,"psVectorSort", "Free float vectors");
+    psFree(in);
+    psFree(out);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psVectorSort", "Free float vectors", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psVectorSort_02.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psVectorSort_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psVectorSort_02.c	(revision 1553)
@@ -0,0 +1,73 @@
+/** @file  tst_psVectorSort_02.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This test driver contains the following tests for psVectorSort test point 2:
+ *     A)  Create vectors
+ *     B)  Sort integer vector of indices based on pre-sort order of floating point vector
+ *     C)  Free vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    psVector *in = NULL;
+    psVector *out = NULL;
+
+
+    // Test A - Create float vectors
+    printPositiveTestHeader(stdout,"psVectorSortIndex", "Create vectors");
+    in = psVectorAlloc(5, PS_TYPE_F32);
+    in->n = 5;
+    in->data.F32[0] = 7.0f;
+    in->data.F32[1] = 9.0f;
+    in->data.F32[2] = 3.0f;
+    in->data.F32[3] = 1.0f;
+    in->data.F32[4] = 5.0f;
+    for(int i=0; i<5; i++) {
+        printf("arr[%d] = %f\n", i, in->data.F32[i]);
+    }
+    printFooter(stdout, "psVectorSortIndex", "Create vectors", true);
+
+
+    // Test B - Sort integer vector of indices based on pre-sort order of floating point vector
+    printPositiveTestHeader(stdout,"psVectorSortIndex", "Create sorted index vector");
+    out = psVectorSortIndex(out, in);
+    for(int i=0; i<5; i++) {
+        printf("arr[%d] = %d\n", i, out->data.U32[i]);
+    }
+    printFooter(stdout, "psVectorSortIndex", "Create sorted index vector", true);
+
+    // Test D - Verify the output vector is of type psU32
+    printPositiveTestHeader(stdout,"psVectorSortIndex", "Verify output vector type");
+    if(out->type.type != PS_TYPE_U32) {
+        printf("ERROR: output vector is of type %d\n", out->type.type);
+    }
+    printFooter(stdout, "psVectorSortIndex", "Verify output vector type", true);
+
+    // Test C - Free vectors
+    printPositiveTestHeader(stdout,"psVectorSortIndex", "Free vectors");
+    psFree(in);
+    psFree(out);
+    int nLeaks = psMemCheckLeaks(0, NULL, stdout);
+    if(nLeaks) {
+        printf("ERROR: Found %d memory leaks\n", nLeaks);
+    }
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psVectorSort", "Free vectors", true);
+
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psVectorSort_03.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psVectorSort_03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psVectorSort_03.c	(revision 1553)
@@ -0,0 +1,84 @@
+/** @file  tst_psVectorSort_03.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This test driver contains the following tests for psVectorSort test point 3:
+ *     A)  Create float vectors of different sizes
+ *     B)  Attempt to sort vectors...should get errors
+ *     C)  Create float vector and double vector
+ *     D)  Attempt to sort vectors...should get errors
+ *     E)  Free float, double vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    psVector *in = NULL;
+    psVector *out = NULL;
+    psVector *in2 = NULL;
+    psVector *out2 = NULL;
+
+    // Test A - Create float vectors
+    printPositiveTestHeader(stdout,"psVectorSort", "Create float vectors of different sizes");
+    in = psVectorAlloc(5, PS_TYPE_F32);
+    in->n = 5;
+    out = psVectorAlloc(6, PS_TYPE_F32);
+    out->n = 6;
+    in->n = 5;
+    for(int i=0; i<5; i++) {
+        printf("arr[%d] = %f\n", i, in->data.F32[i]);
+    }
+    printFooter(stdout, "psVectorSort", "Create float vectors of different sizes", true);
+
+
+    // Test B - Sort input float vector and put results into output float vector
+    printNegativeTestHeader(stdout,"psVectorSort", "Sort float vector",
+                            "Input and output vector sizes are not equal", 0);
+    out = psVectorSort(out, in);
+    printFooter(stdout, "psVectorSort", "Sort float vector", true);
+
+    // Test C - Create float vector and double vector
+    printPositiveTestHeader(stdout,"psVectorSort","Create float & double vectors of same size");
+    in2 = psVectorAlloc(5, PS_TYPE_F32);
+    in2->n = 5;
+    out2 = psVectorAlloc(5, PS_TYPE_F64);
+    out2->n = 5;
+    for(int j=0; j<5; j++) {
+        printf("vec[%d] = %f\n", j, in2->data.F32[j]);
+    }
+    printFooter(stdout, "psVectorSort", "Create float and double vectors same size", true);
+
+    // Test D - Attempt to sort vectors with output of different type should create error
+    printNegativeTestHeader(stdout,"psVectorSort", "Sort F32/F64 vector",
+                            "Input and output vector different types", 0);
+    out2 = psVectorSort(out2, in2);
+    printFooter(stdout, "psVectorSort", "Sort float vector", true);
+
+    // Test C - Free float vectors
+    printPositiveTestHeader(stdout,"psVectorSort", "Free float vectors");
+    psFree(in);
+    psFree(in2);
+    psFree(out);
+    psFree(out2);
+    int nLeaks = psMemCheckLeaks(0, NULL, stdout);
+    if(nLeaks) {
+        printf("ERROR: Found %d memory leaks\n", nLeaks);
+    }
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psVectorSort", "Free float vectors", true);
+
+}
Index: /tags/rel2_1/psLib/test/collections/tst_psVectorSort_04.c
===================================================================
--- /tags/rel2_1/psLib/test/collections/tst_psVectorSort_04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/tst_psVectorSort_04.c	(revision 1553)
@@ -0,0 +1,47 @@
+/** @file  tst_psVectorSort_04.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This test driver contains the following tests for psVectorSort test point 4:
+ *     A)  Attempt to sort with null input vector
+ *     B)  Free vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:05 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    psVector *badIn = NULL;
+    psVector *goodOut = psVectorAlloc(5, PS_TYPE_F32);
+
+    // Test A - Attempt to sort with null input vector
+    printNegativeTestHeader(stdout,"psVectorSort", "Attempt to sort with null input vector",
+                            "Null input vector", 0);
+    goodOut = psVectorSort(goodOut, badIn);
+    printFooter(stdout, "psVectorSort", "Attempt to sort with null input vector", true);
+
+    // Test B - Free vectors
+    printPositiveTestHeader(stdout, "psVectorSort", "Free vectors");
+    psFree(goodOut);
+    int nLeaks = psMemCheckLeaks(0, NULL, stdout);
+    if(nLeaks) {
+        printf("ERROR: Found %d memory blocks\n", nLeaks);
+    }
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psVectorSort", "Free arays", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psArray.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psArray.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psArray.stdout	(revision 1553)
@@ -0,0 +1,70 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psArray.c                                              *
+*            TestPoint: psArray{Create void pointer array}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psArray{Create void pointer array} | tst_psArray.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psArray.c                                              *
+*            TestPoint: psArray{Add data to void pointer array}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+array size = 5
+array population = 5
+
+---> TESTPOINT PASSED (psArray{Add data to void pointer array} | tst_psArray.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psArray.c                                              *
+*            TestPoint: psArray{Reallocate void pointer array bigger}              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Adding more elements to void pointer array...
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+ts[5].x = 50 ts[5].y = 50.50
+ts[6].x = 60 ts[6].y = 60.60
+ts[7].x = 70 ts[7].y = 70.70
+ts[8].x = 80 ts[8].y = 80.80
+ts[9].x = 90 ts[9].y = 90.90
+array size = 10
+array population = 10
+
+---> TESTPOINT PASSED (psArray{Reallocate void pointer array bigger} | tst_psArray.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psArray.c                                              *
+*            TestPoint: psArray{Reallocate void pointer array smaller}             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+array size = 3
+array population = 3
+
+---> TESTPOINT PASSED (psArray{Reallocate integer void pointer smaller} | tst_psArray.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psArray.c                                              *
+*            TestPoint: psArray{Free void pointer array}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psArray{Free void pointer array} | tst_psArray.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stderr	(revision 1553)
@@ -0,0 +1,6 @@
+<DATE><TIME>|<HOST>|E|   psBitSetTest| : Line <LINENO> - Bit position too small: -4
+<DATE><TIME>|<HOST>|E|   psBitSetTest| : Line <LINENO> - Bit position too large: 200
+<DATE><TIME>|<HOST>|E|   psBitSetTest| : Line <LINENO> - Null psBitSet for inBitSet argument
+<DATE><TIME>|<HOST>|E|    psBitSetSet| : Line <LINENO> - Bit position too small: -4
+<DATE><TIME>|<HOST>|E|    psBitSetSet| : Line <LINENO> - Bit position too large: 200
+<DATE><TIME>|<HOST>|E|    psBitSetSet| : Line <LINENO> - Null psBitSet for inBitSet argument
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_01.stdout	(revision 1553)
@@ -0,0 +1,116 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Create psBitSet}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Creating psBitSet with 24 bits...
+000000000000000000000000
+
+
+---> TESTPOINT PASSED (psBitSet{Create psBitSet} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Set bits}                                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Setting first bit...
+Setting third bit...
+Setting last bit...
+100000000000000000000101
+
+
+---> TESTPOINT PASSED (psBitSet{Set bits} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Test bits}                                        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Testing first bit...
+Result: 1
+Testing third bit...
+Result: 1
+Testing last bit...
+Result: 1
+
+---> TESTPOINT PASSED (psBitSet{Test bits} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to test negative bit}                     *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Bit position too small: -4                                 *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to test negative bit} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to test bit to large}                     *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Bit position too large: 200                                *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to test bit to large} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to test bit in null BitSet}               *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null psBitSet for inBitSet argument                        *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to test bit in null BitSet} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to set negative bit}                      *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Bit position too small: -4                                 *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to set negative bit} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to set bit to large}                      *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Bit position too large: 200                                *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to set bit to large} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Attempt to set bit in null BitSet}                *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null psBitSet for inBitSet argument                        *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt to set bit in null BitSet} | tst_psBitSet_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_01.c                                          *
+*            TestPoint: psBitSet{Free psBitSet}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSet} | tst_psBitSet_01.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_02.stdout	(revision 1553)
@@ -0,0 +1,47 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_02.c                                          *
+*            TestPoint: psBitSet{Create two psBitSets}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+000000000000000000000000
+000000000000000000000000
+
+Setting all bits true...
+111111111111111111111111
+111111111111111111111111
+
+
+---> TESTPOINT PASSED (psBitSet{Create two psBitSets} | tst_psBitSet_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_02.c                                          *
+*            TestPoint: psBitSet{Perform binary AND with psBitSets}                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Result:
+111111111111111111111111
+
+---> TESTPOINT PASSED (psBitSet{Perform binary AND with psBitSets} | tst_psBitSet_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_02.c                                          *
+*            TestPoint: psBitSet{Perform binary AND and auto allocate output}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Result:
+111111111111111111111111
+
+---> TESTPOINT PASSED (psBitSet{Perform binary AND and auto allocate output} | tst_psBitSet_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_02.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_02.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_03.stdout	(revision 1553)
@@ -0,0 +1,36 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_03.c                                          *
+*            TestPoint: psBitSet{Create two psBitSets}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+000000000000000000000000
+000000000000000000000000
+
+Setting all bits true...
+111111111111111111111111
+111111111111111111111111
+
+
+---> TESTPOINT PASSED (psBitSet{Create two psBitSets} | tst_psBitSet_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_03.c                                          *
+*            TestPoint: psBitSet{Perform binary OR with psBitSets}                 *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Result:
+111111111111111111111111
+
+---> TESTPOINT PASSED (psBitSet{Perform binary OR with psBitSets} | tst_psBitSet_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_03.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_03.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_04.stdout	(revision 1553)
@@ -0,0 +1,36 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_04.c                                          *
+*            TestPoint: psBitSet{Create two psBitSets}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+000000000000000000000000
+000000000000000000000000
+
+Setting all bits true...
+111111111111111111111111
+111111111111111111111111
+
+
+---> TESTPOINT PASSED (psBitSet{Create two psBitSets} | tst_psBitSet_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_04.c                                          *
+*            TestPoint: psBitSet{Perform binary XOR with psBitSets}                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Result:
+000000000000000000000000
+
+---> TESTPOINT PASSED (psBitSet{Perform binary XOR with psBitSets} | tst_psBitSet_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_04.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_04.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stderr	(revision 1553)
@@ -0,0 +1,1 @@
+<DATE><TIME>|<HOST>|E|     psBitSetOp| : Line <LINENO> - psBitSet sizes not the same
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_05.stdout	(revision 1553)
@@ -0,0 +1,32 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_05.c                                          *
+*            TestPoint: psBitSet{Create two psBitSets of different size}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+000000000000000000000000
+0000000000000000000000000000000000000000
+
+
+---> TESTPOINT PASSED (psBitSet{Create two psBitSets of different size} | tst_psBitSet_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_05.c                                          *
+*            TestPoint: psBitSet{Attempt OR with psBitsets}                        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: psBitSet sizes not the same                                *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt OR with psBitsets} | tst_psBitSet_05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_05.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_05.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stderr	(revision 1553)
@@ -0,0 +1,2 @@
+<DATE><TIME>|<HOST>|E|     psBitSetOp| : Line <LINENO> - Invalid psBitMask binary operation: ZZXOR
+<DATE><TIME>|<HOST>|E|  psBitSetAlloc| : Line <LINENO> - Allocation size must be > 0: size = -4
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_06.stdout	(revision 1553)
@@ -0,0 +1,43 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_06.c                                          *
+*            TestPoint: psBitSet{Create two psBitSets}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+000000000000000000000000
+000000000000000000000000
+
+
+---> TESTPOINT PASSED (psBitSet{Create two psBitSets} | tst_psBitSet_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_06.c                                          *
+*            TestPoint: psBitSet{Perform invalid binary operation}                 *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid psBitMask binary operation                         *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Perform binary XOR with psBitSets} | tst_psBitSet_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_06.c                                          *
+*            TestPoint: psBitSet{Create negative size bitset}                      *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Allocation size must be >= 0: size = -4                    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Create negative size bitset} | tst_psBitSet_06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_06.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSetFree psBitSets} | tst_psBitSet_06.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_07.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_07.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_07.stdout	(revision 1553)
@@ -0,0 +1,49 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_07.c                                          *
+*            TestPoint: psBitSet{Create psBitSets of non-multiple of 8 bits}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Creating psBitSets
+00000000
+00000000
+
+
+---> TESTPOINT PASSED (psBitSet{Create psBitSets of non-multiple of 8 bits} | tst_psBitSet_07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_07.c                                          *
+*            TestPoint: psBitSet{Set psBitSets to 0x3 and 0x5}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+00000011
+00000101
+
+
+---> TESTPOINT PASSED (psBitSet{Set psBitSets to 0x3 and 0x5} | tst_psBitSet_07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_07.c                                          *
+*            TestPoint: psBitSet{Perform AND, OR, and XOR}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+AND:
+00000001
+OR:
+00000111
+XOR:
+00000110
+
+---> TESTPOINT PASSED (psBitSet{Perform AND, OR, and XOR} | tst_psBitSet_07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_07.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_07.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stderr	(revision 1553)
@@ -0,0 +1,1 @@
+<DATE><TIME>|<HOST>|E|    psBitSetNot| : Line <LINENO> - Null psBitSet for inBitSet argument
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psBitSet_08.stdout	(revision 1553)
@@ -0,0 +1,47 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_08.c                                          *
+*            TestPoint: psBitSet{Create psBitSets and set to 0xAA and 0xFF 0xCC}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Creating psBitSets
+10101010
+11111111
+00001100
+
+
+---> TESTPOINT PASSED (psBitSet{Create psBitSets and set to 0xAA and 0xFF 0xCC} | tst_psBitSet_08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_08.c                                          *
+*            TestPoint: psBitSet{Perform NOT operation and auto allocate output}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+01010101
+00000000
+11110011
+
+
+---> TESTPOINT PASSED (psBitSet{Perform NOT operation and auto allocate output} | tst_psBitSet_08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_08.c                                          *
+*            TestPoint: psBitSet{Attempt NOT operation if input argument is NULL}  *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null psBitSet for inBitSet argument                        *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Attempt NOT operation if input argument is NULL} | tst_psBitSet_08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psBitSet_08.c                                          *
+*            TestPoint: psBitSet{Free psBitSets}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Free psBitSets} | tst_psBitSet_08.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psHash00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psHash00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psHash00.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash00.c                                             *
+*            TestPoint: psHash functions{psHashAlloc()}                            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashAlloc()} | tst_psHash00.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psHash01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psHash01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psHash01.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash01.c                                             *
+*            TestPoint: psHash functions{psHashFree()}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashFree()} | tst_psHash01.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psHash03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psHash03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psHash03.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash03.c                                             *
+*            TestPoint: psHash functions{psHashRemove()}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashRemove()} | tst_psHash03.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psHash04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psHash04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psHash04.stdout	(revision 1553)
@@ -0,0 +1,13 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash04.c                                             *
+*            TestPoint: psHash functions{psHashKeyList()}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Linked List Entries: ENTRY03
+Linked List Entries: ENTRY02
+Linked List Entries: ENTRY01
+Linked List Entries: ENTRY00
+
+---> TESTPOINT PASSED (psHash functions{psHashKeyList()} | tst_psHash04.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psList.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psList.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psList.stderr	(revision 1553)
@@ -0,0 +1,95 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListAlloc}                                        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|  testListAlloc|psListAlloc shall create a psList with either 0 or 1 element.
+
+---> TESTPOINT PASSED (psList{psListAlloc} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListAdd}                                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|    testListAdd|psListAdd shall add an element to list
+<DATE><TIME>|<HOST>|I|    testListAdd|Following should error with invalid insert location
+<DATE><TIME>|<HOST>|W|      psListAdd|The given insert location (-10) for psListAdd is invalid.
+<DATE><TIME>|<HOST>|I|    testListAdd|Following should be a warning.
+<DATE><TIME>|<HOST>|W|      psListAdd|Invalid index 9 (only 6 elements in psList); assuming tail.
+
+---> TESTPOINT PASSED (psList{psListAdd} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListGet}                                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|    testListGet|Following should be an error
+<DATE><TIME>|<HOST>|E|listSetIterator|Unexpected null pointer for psList parameter (psList.c:<LINENO>).
+
+---> TESTPOINT PASSED (psList{psListGet} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListRemove}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I| testListRemove|Following should be an error
+<DATE><TIME>|<HOST>|E|   psListRemove|list parameter found to be NULL in psListRemove
+<DATE><TIME>|<HOST>|I| testListRemove|Next message should be an error
+<DATE><TIME>|<HOST>|E|   psListRemove|Couldn't position to given index (-4) to remove element from list.
+<DATE><TIME>|<HOST>|I| testListRemove|Next message should be an error
+<DATE><TIME>|<HOST>|E|   psListRemove|Couldn't position to given index (-2) to remove element from list.
+<DATE><TIME>|<HOST>|I| testListRemove|Next message should be an error
+<DATE><TIME>|<HOST>|E|   psListRemove|Failed to find item in given psList.
+<DATE><TIME>|<HOST>|I| testListRemove|Next message should be an error
+<DATE><TIME>|<HOST>|E|   psListRemove|Failed to find item in given psList.
+
+---> TESTPOINT PASSED (psList{psListRemove} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListConvert}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psList{psListConvert} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListIterator}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testListIterato| psListSetIterator/psListGetNext/psListGetPrev shall move the list cursor to the specified location
+<DATE><TIME>|<HOST>|I|testListIterato|Following should error with 'Unexpected null pointer'
+<DATE><TIME>|<HOST>|E|listSetIterator|Unexpected null pointer for psList parameter (psList.c:<LINENO>).
+<DATE><TIME>|<HOST>|I|testListIterato|Following should error with 'Can't move to an unknown position.'
+<DATE><TIME>|<HOST>|E|listSetIterator|Can't move to an unknown position.  Not moving the iterator position.
+
+---> TESTPOINT PASSED (psList{psListIterator} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListFree}                                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psList{psListFree} | tst_psList.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psList.c                                               *
+*            TestPoint: psList{psListSort}                                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psList{psListSort} | tst_psList.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_01.stdout	(revision 1553)
@@ -0,0 +1,57 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_01.c                                            *
+*            TestPoint: psSort{Create float vectors}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = 7.000000
+vec[1] = 9.000000
+vec[2] = 3.000000
+vec[3] = 1.000000
+vec[4] = 5.000000
+vec[5] = 5.000000
+vec[6] = -20.000000
+
+---> TESTPOINT PASSED (psSort{Create float vectors} | tst_psSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_01.c                                            *
+*            TestPoint: psSort{Sort float vector}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = -20.000000
+vec[1] = 1.000000
+vec[2] = 3.000000
+vec[3] = 5.000000
+vec[4] = 5.000000
+vec[5] = 7.000000
+vec[6] = 9.000000
+
+---> TESTPOINT PASSED (psSort{Sort float vector} | tst_psSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_01.c                                            *
+*            TestPoint: psSort{Sort input float vector into itself}                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = -20.000000
+vec[1] = 1.000000
+vec[2] = 3.000000
+vec[3] = 5.000000
+vec[4] = 5.000000
+vec[5] = 7.000000
+vec[6] = 9.000000
+
+---> TESTPOINT PASSED (psSort{Sort input float vector into itself} | tst_psSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_01.c                                            *
+*            TestPoint: psSort{Free float vectors}                                 *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Free float vectors} | tst_psSort_01.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_02.stdout	(revision 1553)
@@ -0,0 +1,37 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_02.c                                            *
+*            TestPoint: psSort{Create vectors}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 7.000000
+arr[1] = 9.000000
+arr[2] = 3.000000
+arr[3] = 1.000000
+arr[4] = 5.000000
+
+---> TESTPOINT PASSED (psSort{Create vectors} | tst_psSort_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_02.c                                            *
+*            TestPoint: psSort{Create sorted index vector}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 3
+arr[1] = 2
+arr[2] = 4
+arr[3] = 0
+arr[4] = 1
+
+---> TESTPOINT PASSED (psSort{Create sorted index vector} | tst_psSort_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_02.c                                            *
+*            TestPoint: psSort{Free vectors}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Free vectors} | tst_psSort_02.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stderr	(revision 1553)
@@ -0,0 +1,1 @@
+ <DATE> <TIME> |<HOST>|E|         psSort| : Line 137 - Input and output vector sizes are not equal: in=5 out=6
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_03.stdout	(revision 1553)
@@ -0,0 +1,34 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_03.c                                            *
+*            TestPoint: psSort{Create float vectors of different sizes}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 0.000000
+arr[1] = 0.000000
+arr[2] = 0.000000
+arr[3] = 0.000000
+arr[4] = 0.000000
+
+---> TESTPOINT PASSED (psSort{Create float vectors of different sizes} | tst_psSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_03.c                                            *
+*            TestPoint: psSort{Sort float vector}                                  *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Input and output vector sizes are not equal                *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Sort float vector} | tst_psSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_03.c                                            *
+*            TestPoint: psSort{Free float vectors}                                 *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Free float vectors} | tst_psSort_03.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stderr	(revision 1553)
@@ -0,0 +1,1 @@
+ <DATE> <TIME> |<HOST>|E|         psSort| : Line 119 - Null input vector
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psSort_04.stdout	(revision 1553)
@@ -0,0 +1,20 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_04.c                                            *
+*            TestPoint: psSort{Attempt to sort with null input vector}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null input vector                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Attempt to sort with null input vector} | tst_psSort_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psSort_04.c                                            *
+*            TestPoint: psSort{Free vectors}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psSort{Free arays} | tst_psSort_04.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stderr	(revision 1553)
@@ -0,0 +1,4 @@
+<DATE><TIME>|<HOST>|I|           main|Following should be an error message.
+<DATE><TIME>|<HOST>|E|  psVectorAlloc|Invalid value for nalloc. nalloc: 0
+<DATE><TIME>|<HOST>|I|           main|Following should be an error message.
+<DATE><TIME>|<HOST>|E|psVectorRealloc|Null input vector
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector.stdout	(revision 1553)
@@ -0,0 +1,91 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Create S32 vector}                                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 5
+Vector type = 260
+Vector dimen = 1
+
+---> TESTPOINT PASSED (psVector{Create S32 vector} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Add data to S32 vector}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Elem 0 = 0
+Elem 1 = 10
+Elem 2 = 20
+Elem 3 = 30
+Elem 4 = 40
+Vector size = 5
+Vector population = 5
+
+---> TESTPOINT PASSED (psVector{Add data to S32 vector} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Reallocate S32 vector bigger}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Adding more elements to S32 vector...
+Elem 5 = 50
+Elem 6 = 60
+Elem 7 = 70
+Elem 8 = 80
+Elem 9 = 90
+Vector size = 10
+Vector population = 10
+
+---> TESTPOINT PASSED (psVector{Reallocate S32 vector bigger} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Reallocate S32 vector smaller}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 3
+Elem 0 = 0
+Elem 1 = 10
+Elem 2 = 20
+Vector size = 3
+Vector population = 3
+
+---> TESTPOINT PASSED (psVector{Reallocate integer S32 smaller} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Free S32 vector}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Free S32 vector} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Attempt to create a S32 vector with zero size}    *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid value for nalloc                                   *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Attempt to create a S32 vector with zero size} | tst_psVector.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector.c                                             *
+*            TestPoint: psVector{Attempt to realloc a null S32 vector}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null input vector                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Attempt to realloc a null S32 vector} | tst_psVector.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_01.stdout	(revision 1553)
@@ -0,0 +1,57 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_01.c                                      *
+*            TestPoint: psVectorSort{Create float vectors}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = 7.000000
+vec[1] = 9.000000
+vec[2] = 3.000000
+vec[3] = 1.000000
+vec[4] = 5.000000
+vec[5] = 5.000000
+vec[6] = -20.000000
+
+---> TESTPOINT PASSED (psVectorSort{Create float vectors} | tst_psVectorSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_01.c                                      *
+*            TestPoint: psVectorSort{Sort float vector}                            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = -20.000000
+vec[1] = 1.000000
+vec[2] = 3.000000
+vec[3] = 5.000000
+vec[4] = 5.000000
+vec[5] = 7.000000
+vec[6] = 9.000000
+
+---> TESTPOINT PASSED (psVectorSort{Sort float vector} | tst_psVectorSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_01.c                                      *
+*            TestPoint: psVectorSort{Sort input float vector into itself}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = -20.000000
+vec[1] = 1.000000
+vec[2] = 3.000000
+vec[3] = 5.000000
+vec[4] = 5.000000
+vec[5] = 7.000000
+vec[6] = 9.000000
+
+---> TESTPOINT PASSED (psVectorSort{Sort input float vector into itself} | tst_psVectorSort_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_01.c                                      *
+*            TestPoint: psVectorSort{Free float vectors}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Free float vectors} | tst_psVectorSort_01.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_02.stdout	(revision 1553)
@@ -0,0 +1,46 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_02.c                                      *
+*            TestPoint: psVectorSortIndex{Create vectors}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 7.000000
+arr[1] = 9.000000
+arr[2] = 3.000000
+arr[3] = 1.000000
+arr[4] = 5.000000
+
+---> TESTPOINT PASSED (psVectorSortIndex{Create vectors} | tst_psVectorSort_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_02.c                                      *
+*            TestPoint: psVectorSortIndex{Create sorted index vector}              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 3
+arr[1] = 2
+arr[2] = 4
+arr[3] = 0
+arr[4] = 1
+
+---> TESTPOINT PASSED (psVectorSortIndex{Create sorted index vector} | tst_psVectorSort_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_02.c                                      *
+*            TestPoint: psVectorSortIndex{Verify output vector type}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSortIndex{Verify output vector type} | tst_psVectorSort_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_02.c                                      *
+*            TestPoint: psVectorSortIndex{Free vectors}                            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Free vectors} | tst_psVectorSort_02.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stderr	(revision 1553)
@@ -0,0 +1,2 @@
+<DATE><TIME>|<HOST>|E|   psVectorSort| : Line <LINENO> - Input and output vector sizes are not equal: in=5 out=6
+<DATE><TIME>|<HOST>|E|   psVectorSort| : Line <LINENO> - Input and output vectors are not same type: in=1028 out=1032
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_03.stdout	(revision 1553)
@@ -0,0 +1,59 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_03.c                                      *
+*            TestPoint: psVectorSort{Create float vectors of different sizes}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+arr[0] = 0.000000
+arr[1] = 0.000000
+arr[2] = 0.000000
+arr[3] = 0.000000
+arr[4] = 0.000000
+
+---> TESTPOINT PASSED (psVectorSort{Create float vectors of different sizes} | tst_psVectorSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_03.c                                      *
+*            TestPoint: psVectorSort{Sort float vector}                            *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Input and output vector sizes are not equal                *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Sort float vector} | tst_psVectorSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_03.c                                      *
+*            TestPoint: psVectorSort{Create float & double vectors of same size}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+vec[0] = 0.000000
+vec[1] = 0.000000
+vec[2] = 0.000000
+vec[3] = 0.000000
+vec[4] = 0.000000
+
+---> TESTPOINT PASSED (psVectorSort{Create float and double vectors same size} | tst_psVectorSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_03.c                                      *
+*            TestPoint: psVectorSort{Sort F32/F64 vector}                          *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Input and output vector different types                    *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Sort float vector} | tst_psVectorSort_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_03.c                                      *
+*            TestPoint: psVectorSort{Free float vectors}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Free float vectors} | tst_psVectorSort_03.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stderr	(revision 1553)
@@ -0,0 +1,1 @@
+<DATE><TIME>|<HOST>|E|   psVectorSort| : Line <LINENO> - Null input vector
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVectorSort_04.stdout	(revision 1553)
@@ -0,0 +1,20 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_04.c                                      *
+*            TestPoint: psVectorSort{Attempt to sort with null input vector}       *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null input vector                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Attempt to sort with null input vector} | tst_psVectorSort_04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorSort_04.c                                      *
+*            TestPoint: psVectorSort{Free vectors}                                 *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVectorSort{Free arays} | tst_psVectorSort_04.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stderr	(revision 1553)
@@ -0,0 +1,2 @@
+ <DATE> <TIME> |<HOST>|E|  psVectorAlloc|Invalid value for nalloc. nalloc: 0
+ <DATE> <TIME> |<HOST>|E|psVectorRealloc|Null input vector
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector_01.stdout	(revision 1553)
@@ -0,0 +1,91 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Create S32 vector}                                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 5
+Vector type = 260
+Vector dimen = 1
+
+---> TESTPOINT PASSED (psVector{Create S32 vector} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Add data to S32 vector}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Elem 0 = 0
+Elem 1 = 10
+Elem 2 = 20
+Elem 3 = 30
+Elem 4 = 40
+Vector size = 5
+Vector population = 5
+
+---> TESTPOINT PASSED (psVector{Add data to S32 vector} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Reallocate S32 vector bigger}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Adding more elements to S32 vector...
+Elem 5 = 50
+Elem 6 = 60
+Elem 7 = 70
+Elem 8 = 80
+Elem 9 = 90
+Vector size = 10
+Vector population = 10
+
+---> TESTPOINT PASSED (psVector{Reallocate S32 vector bigger} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Reallocate S32 vector smaller}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 3
+Elem 0 = 0
+Elem 1 = 10
+Elem 2 = 20
+Vector size = 3
+Vector population = 3
+
+---> TESTPOINT PASSED (psVector{Reallocate integer S32 smaller} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Free S32 vector}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Free S32 vector} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Attempt to create a S32 vector with zero size}    *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid value for nalloc                                   *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Attempt to create a S32 vector with zero size} | tst_psVector_01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_01.c                                          *
+*            TestPoint: psVector{Attempt to realloc a null S32 vector}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null input vector                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Attempt to realloc a null S32 vector} | tst_psVector_01.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector_02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector_02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector_02.stdout	(revision 1553)
@@ -0,0 +1,73 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_02.c                                          *
+*            TestPoint: psVector{Create void pointer vector}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 5
+Vector type = 0
+Vector dimen = 1
+
+---> TESTPOINT PASSED (psVector{Create void pointer vector} | tst_psVector_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_02.c                                          *
+*            TestPoint: psVector{Add data to void pointer vector}                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+Vector size = 5
+Vector population = 5
+
+---> TESTPOINT PASSED (psVector{Add data to void pointer vector} | tst_psVector_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_02.c                                          *
+*            TestPoint: psVector{Reallocate void pointer vector bigger}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Adding more elements to void pointer vector...
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+ts[5].x = 50 ts[5].y = 50.50
+ts[6].x = 60 ts[6].y = 60.60
+ts[7].x = 70 ts[7].y = 70.70
+ts[8].x = 80 ts[8].y = 80.80
+ts[9].x = 90 ts[9].y = 90.90
+Vector size = 10
+Vector population = 10
+
+---> TESTPOINT PASSED (psVector{Reallocate void pointer vector bigger} | tst_psVector_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_02.c                                          *
+*            TestPoint: psVector{Reallocate void pointer vector smaller}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+Vector size = 3
+Vector population = 3
+
+---> TESTPOINT PASSED (psVector{Reallocate integer void pointer smaller} | tst_psVector_02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_02.c                                          *
+*            TestPoint: psVector{Free void pointer vector}                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Free void pointer vector} | tst_psVector_02.c)
+
Index: /tags/rel2_1/psLib/test/collections/verified/tst_psVector_03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/collections/verified/tst_psVector_03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/collections/verified/tst_psVector_03.stdout	(revision 1553)
@@ -0,0 +1,73 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_03.c                                          *
+*            TestPoint: psVector{Create void pointer vector}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Vector size = 5
+Vector type = 0
+Vector dimen = 1
+
+---> TESTPOINT PASSED (psVector{Create void pointer vector} | tst_psVector_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_03.c                                          *
+*            TestPoint: psVector{Add data to void pointer vector}                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+Vector size = 5
+Vector population = 5
+
+---> TESTPOINT PASSED (psVector{Add data to void pointer vector} | tst_psVector_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_03.c                                          *
+*            TestPoint: psVector{Reallocate void pointer vector bigger}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Adding more elements to void pointer vector...
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+ts[3].x = 30 ts[3].y = 30.30
+ts[4].x = 40 ts[4].y = 40.40
+ts[5].x = 50 ts[5].y = 50.50
+ts[6].x = 60 ts[6].y = 60.60
+ts[7].x = 70 ts[7].y = 70.70
+ts[8].x = 80 ts[8].y = 80.80
+ts[9].x = 90 ts[9].y = 90.90
+Vector size = 10
+Vector population = 10
+
+---> TESTPOINT PASSED (psVector{Reallocate void pointer vector bigger} | tst_psVector_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_03.c                                          *
+*            TestPoint: psVector{Reallocate void pointer vector smaller}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ts[0].x = 0 ts[0].y = 0.00
+ts[1].x = 10 ts[1].y = 10.10
+ts[2].x = 20 ts[2].y = 20.20
+Vector size = 3
+Vector population = 3
+
+---> TESTPOINT PASSED (psVector{Reallocate integer void pointer smaller} | tst_psVector_03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVector_03.c                                          *
+*            TestPoint: psVector{Free void pointer array with function callback}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector{Free void pointer array with function callback} | tst_psVector_03.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/.cvsignore	(revision 1553)
@@ -0,0 +1,41 @@
+temp
+tmpImages
+tst_psMatrix01
+tst_psStats00
+tst_psStats01
+tst_psStats02
+tst_psStats03
+tst_psStats04
+tst_psFunc00
+tst_psFunc01
+tst_psHist00
+tst_psHist01
+tst_psHist02
+tst_psImageIO
+tst_psImageStats00
+tst_psImageStats01
+tst_psImageStats02
+tst_psMatrix02
+tst_psMatrix03
+tst_psMatrix04
+tst_psMatrix05
+tst_psMatrix06
+tst_psMatrix07
+tst_psStats05
+tst_psStats06
+tst_psStats07
+tst_psStats08
+tst_psStats09
+tst_psImageFFT
+tst_psVectorFFT
+tst_psImageStats03
+tst_psMatrixVectorArithmetic01
+tst_psMatrixVectorArithmetic02
+test/dataManip/tst_psImageManip
+tst_psMatrixVectorArithmetic03
+tst_psMinimize00
+tst_psMinimize01
+tst_psMinimize02
+tst_psMinimize03
+tst_psMinimize04
+tst_psImageManip
Index: /tags/rel2_1/psLib/test/dataManip/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/Makefile	(revision 1553)
@@ -0,0 +1,76 @@
+################################################################################
+##
+##  Makefile:   test/sysUtils
+##
+##  $Revision: 1.35 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-07-28 02:50:38 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+include ../../src/Makefile.Globals
+
+CFLAGS := -I../../include $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+
+TARGET = \
+tst_psFunc00 \
+tst_psFunc01 \
+tst_psHist00 \
+tst_psHist01 \
+tst_psHist02 \
+tst_psMatrix01 \
+tst_psMatrix02 \
+tst_psMatrix03 \
+tst_psMatrix04 \
+tst_psMatrix05 \
+tst_psMatrix06 \
+tst_psMatrix07 \
+tst_psMatrixVectorArithmetic01 \
+tst_psMatrixVectorArithmetic02 \
+tst_psMatrixVectorArithmetic03 \
+tst_psMinimize00 \
+tst_psMinimize01 \
+tst_psMinimize02 \
+tst_psMinimize03 \
+tst_psMinimize04 \
+tst_psStats00 \
+tst_psStats01 \
+tst_psStats02 \
+tst_psStats03 \
+tst_psStats05 \
+tst_psStats06 \
+tst_psStats07 \
+tst_psStats08 \
+tst_psStats09 \
+tst_psVectorFFT 
+
+OBJS = $(addsuffix .o,$(TARGET))
+
+all: $(TARGET)
+
+# include $(DEPENDENCIES)
+
+clean:
+	@echo "    Deleting executable and binary files for 'test/collections'"
+	$(RM) $(OBJS)
+
+distclean: clean
+	$(RM) $(TARGET)
+
+install: $(testbindir) $(testbindir)/verified $(TARGET)
+	install $(TARGET) $(testbindir)
+	install verified/*.stderr verified/*.stdout $(testbindir)/verified
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
+$(testbindir)/verified:
+	mkdir -p $(testbindir)/verified
+
+
Index: /tags/rel2_1/psLib/test/dataManip/tst_psFunc00.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psFunc00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psFunc00.c	(revision 1553)
@@ -0,0 +1,282 @@
+/*****************************************************************************
+    This routine must ensure that the psPolynomial structures are
+    allocated and deallocated by the psPolynomialXXXlloc() procedures.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psFunctions.h"
+#define MISC_FLOAT_NUMBER 345.0
+#define MISC_X_VALUE 5.0
+#define MISC_INT_NUMBER 35
+#define NUM_BINS 200
+#define AN 2
+#define BN 4
+#define CN 6
+#define DN 8
+int main()
+{
+    psPolynomial1D *my1DPoly = NULL;
+    psPolynomial2D *my2DPoly = NULL;
+    psPolynomial3D *my3DPoly = NULL;
+    psPolynomial4D *my4DPoly = NULL;
+    psDPolynomial1D *my1DPolyD = NULL;
+    psDPolynomial2D *my2DPolyD = NULL;
+    psDPolynomial3D *my3DPolyD = NULL;
+    psDPolynomial4D *my4DPolyD = NULL;
+    int testStatus      = true;
+    int memLeaks        = 0;
+    int a               = 0;
+    int b               = 0;
+    int c               = 0;
+    int d               = 0;
+    int currentId       = 0;
+
+    currentId       = psMemGetId();
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psPolynomial1D structure.");
+
+    my1DPoly = psPolynomial1DAlloc(AN);
+    for (a = 0; a < AN ; a++) {
+        my1DPoly->coeff[a] = MISC_FLOAT_NUMBER;
+        my1DPoly->coeffErr[a] = MISC_FLOAT_NUMBER;
+        my1DPoly->mask[a] = MISC_INT_NUMBER;
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x) = (%f): %f\n", MISC_X_VALUE,
+           psPolynomial1DEval(MISC_X_VALUE, my1DPoly));
+
+    psFree(my1DPoly);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psPolynomial1D structure.",
+                testStatus);
+
+
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psPolynomial2D structure.");
+    my2DPoly = psPolynomial2DAlloc(AN, BN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            my2DPoly->coeff[a][b] = MISC_FLOAT_NUMBER;
+            my2DPoly->coeffErr[a][b] = MISC_FLOAT_NUMBER;
+            my2DPoly->mask[a][b] = MISC_INT_NUMBER;
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x, y) = (%f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           psPolynomial2DEval(MISC_X_VALUE, MISC_X_VALUE, my2DPoly));
+
+    psFree(my2DPoly);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psPolynomial2D structure.",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psPolynomial3D structure.");
+    my3DPoly = psPolynomial3DAlloc(AN, BN, CN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            for (c = 0; c < CN ; c++) {
+                my3DPoly->coeff[a][b][c] = MISC_FLOAT_NUMBER;
+                my3DPoly->coeffErr[a][b][c] = MISC_FLOAT_NUMBER;
+                my3DPoly->mask[a][b][c] = MISC_INT_NUMBER;
+            }
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x, y, z) = (%f, %f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           MISC_X_VALUE,
+           psPolynomial3DEval(MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, my3DPoly));
+
+    psFree(my3DPoly);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psPolynomial3D structure.",
+                testStatus);
+
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psPolynomial4D structure.");
+    my4DPoly = psPolynomial4DAlloc(AN, BN, CN, DN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            for (c = 0; c < CN ; c++) {
+                for (d = 0; d < DN ; d++) {
+                    my4DPoly->coeff[a][b][c][d] = MISC_FLOAT_NUMBER;
+                    my4DPoly->coeffErr[a][b][c][d] = MISC_FLOAT_NUMBER;
+                    my4DPoly->mask[a][b][c][d] = MISC_INT_NUMBER;
+                }
+            }
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (w, x, y, z) = (%f, %f, %f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           MISC_X_VALUE, MISC_X_VALUE,
+           psPolynomial4DEval(MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, my4DPoly));
+
+    psFree(my4DPoly);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psPolynomial4D structure.",
+                testStatus);
+
+
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psDPolynomial1D structure.");
+
+    my1DPolyD = psDPolynomial1DAlloc(AN);
+    for (a = 0; a < AN ; a++) {
+        my1DPolyD->coeff[a] = MISC_FLOAT_NUMBER;
+        my1DPolyD->coeffErr[a] = MISC_FLOAT_NUMBER;
+        my1DPolyD->mask[a] = MISC_INT_NUMBER;
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x) = (%f): %f\n", MISC_X_VALUE,
+           psDPolynomial1DEval(MISC_X_VALUE, my1DPolyD));
+
+    psFree(my1DPolyD);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psDPolynomial1D structure.",
+                testStatus);
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psDPolynomial2D structure.");
+    my2DPolyD = psDPolynomial2DAlloc(AN, BN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            my2DPolyD->coeff[a][b] = MISC_FLOAT_NUMBER;
+            my2DPolyD->coeffErr[a][b] = MISC_FLOAT_NUMBER;
+            my2DPolyD->mask[a][b] = MISC_INT_NUMBER;
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x, y) = (%f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           psDPolynomial2DEval(MISC_X_VALUE, MISC_X_VALUE, my2DPolyD));
+
+    psFree(my2DPolyD);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psDPolynomial2D structure.",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psDPolynomial3D structure.");
+    my3DPolyD = psDPolynomial3DAlloc(AN, BN, CN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            for (c = 0; c < CN ; c++) {
+                my3DPolyD->coeff[a][b][c] = MISC_FLOAT_NUMBER;
+                my3DPolyD->coeffErr[a][b][c] = MISC_FLOAT_NUMBER;
+                my3DPolyD->mask[a][b][c] = MISC_INT_NUMBER;
+            }
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (x, y, z) = (%f, %f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           MISC_X_VALUE,
+           psDPolynomial3DEval(MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, my3DPolyD));
+
+    psFree(my3DPolyD);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psDPolynomial3D structure.",
+                testStatus);
+
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "Allocate/Deallocate the psDPolynomial4D structure.");
+    my4DPolyD = psDPolynomial4DAlloc(AN, BN, CN, DN);
+    for (a = 0; a < AN ; a++) {
+        for (b = 0; b < BN ; b++) {
+            for (c = 0; c < CN ; c++) {
+                for (d = 0; d < DN ; d++) {
+                    my4DPolyD->coeff[a][b][c][d] = MISC_FLOAT_NUMBER;
+                    my4DPolyD->coeffErr[a][b][c][d] = MISC_FLOAT_NUMBER;
+                    my4DPolyD->mask[a][b][c][d] = MISC_INT_NUMBER;
+                }
+            }
+        }
+    }
+    psMemCheckCorruption(1);
+
+    printf("At (w, x, y, z) = (%f, %f, %f, %f): %f\n", MISC_X_VALUE, MISC_X_VALUE,
+           MISC_X_VALUE, MISC_X_VALUE,
+           psDPolynomial4DEval(MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, MISC_X_VALUE, my4DPolyD));
+
+    psFree(my4DPolyD);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate/Deallocate the psDPolynomial4D structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psFunc01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psFunc01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psFunc01.c	(revision 1553)
@@ -0,0 +1,76 @@
+/*****************************************************************************
+    This routine must ensure that the psGaussian() shall evaluate a
+    specified Gaussian at some X.
+ 
+    It also tests the psGaussianDev() procedure.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psFunctions.h"
+#define MY_MEAN 30.0
+#define MY_STDEV 2.0
+#define N 30
+int main()
+{
+    int testStatus = true;
+    float x = 0.0;
+    int  memLeaks;
+    int  currentId = psMemGetId();
+    psVector *myGaussData = NULL;
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "psGaussian()");
+
+
+    for (x = 0.0 ; x < (MY_MEAN * 2.0) ; x+= 1.0) {
+        printf("normal psGaussian(%f) is %f\n", x, psGaussian(x, MY_MEAN, MY_STDEV, true));
+        x = x + 1.0;
+    }
+
+    for (x = 0.0 ; x < (MY_MEAN * 2.0) ; x+= 1.0) {
+        printf("NON-normal psGaussian(%f) is %f\n", x, psGaussian(x, MY_MEAN, MY_STDEV, false));
+        x = x + 1.0;
+    }
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psFunctions functions",
+                "psGaussian()",
+                testStatus);
+
+
+    printPositiveTestHeader(stdout,
+                            "psFunctions functions",
+                            "psGaussianDev()");
+
+    myGaussData = psGaussianDev(MY_MEAN, MY_STDEV, N);
+    for (int i = 0; i < N ; i++) {
+        printf("Gaussian Deviate [%d] is %f\n", i, myGaussData->data.F32[i]);
+    }
+
+    if ( myGaussData->type.type != PS_TYPE_F32) {
+        psAbort(__func__,"psGaussianDev did not return a vector of type F32");
+    }
+
+    psFree(myGaussData);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psFunctions functions",
+                "psGaussianDev()",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psHist00.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psHist00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psHist00.c	(revision 1553)
@@ -0,0 +1,124 @@
+/*****************************************************************************
+    This routine must ensure that the psHistogram structure is correctly
+    allocated and deallocated by the procedure psHistogramAlloc().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define LOWER 20.0
+#define UPPER 30.0
+
+int main()
+{
+    psHistogram *myHist = NULL;
+    int testStatus      = true;
+    int memLeaks        = 0;
+    int i               = 0;
+    int nb              = 0;
+    int numBins         = 0;
+    int currentId       = 0;
+
+    currentId       = psMemGetId();
+    for (nb=0;nb<4;nb++) {
+        if (nb == 0)
+            numBins = 1;
+        if (nb == 1)
+            numBins = 2;
+        if (nb == 2)
+            numBins = 10;
+        if (nb == 3)
+            numBins = 20;
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                          */
+        /*********************************************************************/
+        printPositiveTestHeader(stdout,
+                                "psStats functions",
+                                "Allocate the psHistogram structure.");
+
+        myHist = psHistogramAlloc(LOWER, UPPER, numBins);
+
+        if (myHist->nums->n != numBins) {
+            printf("ERROR: myHist->nums->n is wrong size (%d)\n", myHist->nums->n);
+            testStatus = false;
+        }
+
+        if (myHist->bounds->n != numBins+1) {
+            printf("ERROR: myHist->bounds->n is wrong size (%d)\n", myHist->bounds->n);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            if (myHist->nums->data.U32[i] != 0) {
+                printf("ERROR: myHist->nums->data.U32[%d] not initialized to 0.\n", i);
+                testStatus = false;
+            }
+            myHist->nums->data.U32[i] = 0;
+        }
+
+        if (myHist->minNum != 0) {
+            printf("ERROR: myHist->minNum is %d\n", myHist->minNum);
+            testStatus = false;
+        }
+
+        if (myHist->maxNum != 0) {
+            printf("myHist->maxNum is %d\n", myHist->maxNum);
+            testStatus = false;
+        }
+
+        if (myHist->uniform != true) {
+            printf("ERROR: myHist->uniform is %d\n", myHist->uniform);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            printf("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                   myHist->bounds->data.F32[i],
+                   myHist->bounds->data.F32[i+1]);
+        }
+
+        psMemCheckCorruption(1);
+        psFree(myHist);
+        psMemCheckCorruption(1);
+
+        printFooter(stdout,
+                    "psStats functions",
+                    "Allocate the psHistogram structure.",
+                    testStatus);
+    }
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Allocate the psHistogram structure. (UPPER<LOWER)");
+
+    myHist = psHistogramAlloc(UPPER, LOWER, numBins);
+    if (myHist != NULL) {
+        printf("ERROR: myHist != NULL\n");
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate the psHistogram structure. (UPPER<LOWER)",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psHistogram structure.");
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psHistogram structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psHist01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psHist01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psHist01.c	(revision 1553)
@@ -0,0 +1,114 @@
+/*****************************************************************************
+    This routine must ensure that the psHistogram structure is correctly
+    allocated and deallocated by the procedure psHistogramAllocGeneric().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define LOWER 20.0
+#define UPPER 30.0
+
+int main()
+{
+    psHistogram *myHist = NULL;
+    psVector *myBounds  = NULL;
+    int testStatus      = true;
+    int memLeaks        = 0;
+    int i               = 0;
+    int nb              = 0;
+    int numBins         = 0;
+    int currentId       = 0;
+
+    currentId       = psMemGetId();
+    for (nb=0;nb<4;nb++) {
+        if (nb == 0)
+            numBins = 1;
+        if (nb == 1)
+            numBins = 2;
+        if (nb == 2)
+            numBins = 10;
+        if (nb == 3)
+            numBins = 20;
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                          */
+        /*********************************************************************/
+        printPositiveTestHeader(stdout,
+                                "psStats functions",
+                                "Allocate the psHistogram structure.");
+        myBounds = psVectorAlloc(numBins+1, PS_TYPE_F32);
+        myBounds->n = myBounds->nalloc;
+        for (i=0;i<numBins+1;i++) {
+            myBounds->data.F32[i] = LOWER + ((UPPER - LOWER) / (float) numBins) *
+                                    (float) i;
+        }
+        myHist = psHistogramAllocGeneric(myBounds);
+
+        if (myHist->nums->n != numBins) {
+            printf("ERROR: myHist->nums->n is wrong size (%d)\n", myHist->nums->n);
+            testStatus = false;
+        }
+
+        if (myHist->bounds->n != numBins+1) {
+            printf("ERROR: myHist->bounds->n is wrong size (%d)\n", myHist->bounds->n);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            if (myHist->nums->data.U32[i] != 0) {
+                printf("ERROR: myHist->nums->data.U32[%d] not initialized to 0.\n", i);
+                testStatus = false;
+            }
+            myHist->nums->data.U32[i] = 0;
+        }
+
+        if (myHist->minNum != 0) {
+            printf("ERROR: myHist->minNum is %d\n", myHist->minNum);
+            testStatus = false;
+        }
+
+        if (myHist->maxNum != 0) {
+            printf("myHist->maxNum is %d\n", myHist->maxNum);
+            testStatus = false;
+        }
+
+        if (myHist->uniform != false) {
+            printf("ERROR: myHist->uniform is %d\n", myHist->uniform);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            printf("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                   myHist->bounds->data.F32[i],
+                   myHist->bounds->data.F32[i+1]);
+        }
+        psMemCheckCorruption(1);
+        psFree(myHist);
+        psMemCheckCorruption(1);
+        psFree(myBounds);
+
+        printFooter(stdout,
+                    "psStats functions",
+                    "Allocate the psHistogram structure.",
+                    testStatus);
+    }
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psHistogram structure.");
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psHistogram structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psHist02.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psHist02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psHist02.c	(revision 1553)
@@ -0,0 +1,182 @@
+/*****************************************************************************
+   This routine must ensure that the psHistogram structure is correctly
+   populated by the procedure psGetArrayHistogram().
+ 
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define MISC_FLOAT_NUMBER 345.0
+#define MISC_INT_NUMBER 345
+#define LOWER 20.0
+#define UPPER 30.0
+#define NUM_DATA 10000
+
+int main()
+{
+    psHistogram * myHist = NULL;
+    psHistogram *myHist2 = NULL;
+    psVector *myData = NULL;
+    psVector *myMask = NULL;
+    int testStatus = true;
+    int memLeaks = 0;
+    int nb = 0;
+    int numBins = 0;
+    int i = 0;
+    int currentId = 0;
+
+    currentId = psMemGetId();
+
+    /*********************************************************************/
+    /*  Allocate and initialize data structures                          */
+    /*********************************************************************/
+    myData = psVectorAlloc( NUM_DATA, PS_TYPE_F32 );
+    myData->n = myData->nalloc;
+    for ( i = 0;i < NUM_DATA;i++ ) {
+        myData->data.F32[ i ] = LOWER + ( ( UPPER - LOWER ) / ( float ) NUM_DATA ) * ( float ) i;
+    }
+
+    myMask = psVectorAlloc( NUM_DATA, PS_TYPE_U8 );
+    myMask->n = myMask->nalloc;
+    for ( i = 0;i < NUM_DATA;i++ ) {
+        if ( i >= ( NUM_DATA / 2 ) ) {
+            myMask->data.U8[ i ] = 1;
+        } else {
+            myMask->data.U8[ i ] = 0;
+        }
+    }
+
+    for ( nb = 0;nb < 4;nb++ ) {
+        if ( nb == 0 )
+            numBins = 1;
+        if ( nb == 1 )
+            numBins = 2;
+        if ( nb == 2 )
+            numBins = 10;
+        if ( nb == 3 )
+            numBins = 20;
+
+        /*********************************************************************/
+        /*  Allocate and Perform Histogram, no mask                          */
+        /*********************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psStats functions",
+                                 "Allocate and Perform Histogram, no mask" );
+
+        myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+        myHist = psVectorHistogram( myHist, myData, NULL, 0 );
+
+        for ( i = 0;i < numBins;i++ ) {
+            printf( "Bin number %d bounds: (%.2f - %.2f) data (%d)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.U32[ i ] );
+        }
+        psMemCheckCorruption( 1 );
+        psFree( myHist );
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psStats functions",
+                     "Allocate and Perform Histogram, no mask",
+                     testStatus );
+
+        /*********************************************************************/
+        /*  Allocate and Perform Histogram with mask                         */
+        /*********************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psStats functions",
+                                 "Allocate and Perform Histogram with mask" );
+
+        myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+        myHist = psVectorHistogram( myHist, myData, myMask, 1 );
+
+        for ( i = 0;i < numBins;i++ ) {
+            printf( "Bin number %d bounds: (%6.3f - %6.3f) data (%d)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.U32[ i ] );
+        }
+        psMemCheckCorruption( 1 );
+        psFree( myHist );
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psStats functions",
+                     "Allocate and Perform Histogram with mask",
+                     testStatus );
+    }
+    psFree( myMask );
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "Calling psVectorHistogram() with various NULL inputs." );
+
+    // Verify the return value is null and program execution doesn't stop,
+    // if input parameter myHist is null.
+
+    myHist2 = psVectorHistogram( NULL, myData, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        printf( "ERROR: myHist2!=NULL\n" );
+        testStatus = false;
+    }
+    psFree( myData );
+
+
+    // Verify the retrun value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray is
+    // null.
+
+    myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+    myHist = psVectorHistogram( myHist, NULL, NULL, 0 );
+    if ( myHist == NULL ) {
+        printf( "ERROR: myHist==NULL\n" );
+        testStatus = false;
+    }
+    psFree( myHist );
+
+
+    // Verify the return value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray has no
+    // elements.
+    // NOTE: This code segment is commented out because psVectorAlloc returns
+    // NULL if called with an N element data.
+    /*
+    myData = psVectorAlloc(0, PS_TYPE_F32);
+    myData->n = myData->nalloc;
+    myHist = psHistogramAlloc(LOWER, UPPER, numBins);
+    myHist = psVectorHistogram(myHist, NULL, NULL, 0);
+    if (myHist == NULL) {
+        printf("ERROR: myHist==NULL\n");
+        testStatus = false;
+    }
+    psFree(myHist);
+    psFree(myData);
+    */
+    printFooter( stdout,
+                 "psStats functions",
+                 "Calling psVectorHistogram() with various NULL inputs.",
+                 testStatus );
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "Deallocate the psHistogram structure." );
+
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+    if ( 0 != memLeaks ) {
+        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+    }
+    psMemCheckCorruption( 1 );
+
+    printFooter( stdout,
+                 "psStats functions",
+                 "Deallocate the psHistogram structure.",
+                 testStatus );
+
+    return ( !testStatus );
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix01.c	(revision 1553)
@@ -0,0 +1,92 @@
+/** @file  tst_psMatrix_01.c
+*
+*  @brief Test driver for psMatrix transpose function
+*
+*  This test driver contains the following tests for psMatrix test point 1:
+*     A)  Create input and output images
+*     B)  Transpose input image into output image
+*     C)  Transpose input image into auto allocated NULL output image 
+*     D)  Free images and check for leaks
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.6 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-06 22:34:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                         \
+for(int i=IMAGE->numRows-1; i>-1; i--) {        \
+    for(int j=0; j<IMAGE->numCols; j++) {       \
+        printf("%f ", IMAGE->data.F64[i][j]);   \
+    }                                          \
+    printf("\n");                              \
+}
+
+int main( int argc,
+          char* argv[] )
+{
+    psImage * tempImage = NULL;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Create input and output images" );
+    psImage *inImage = ( psImage* ) psImageAlloc( 3, 3, PS_TYPE_F64 );
+    psImage *outImage = ( psImage* ) psImageAlloc( 3, 3, PS_TYPE_F64 );
+    inImage->data.F64[ 0 ][ 0 ] = 1;
+    inImage->data.F64[ 0 ][ 1 ] = 2;
+    inImage->data.F64[ 0 ][ 2 ] = 3;
+    inImage->data.F64[ 1 ][ 0 ] = 4;
+    inImage->data.F64[ 1 ][ 1 ] = 5;
+    inImage->data.F64[ 1 ][ 2 ] = 6;
+    inImage->data.F64[ 2 ][ 0 ] = 7;
+    inImage->data.F64[ 2 ][ 1 ] = 8;
+    inImage->data.F64[ 2 ][ 2 ] = 9;
+    PRINT_MATRIX( inImage );
+    printFooter( stdout, "psMatrix", "Create input and output images", true );
+
+
+    // Test B - Transpose input image into output image
+    printPositiveTestHeader( stdout, "psMatrix", "Transpose input image into output image" );
+    tempImage = outImage;
+    outImage = psMatrixTranspose( outImage, inImage );
+    PRINT_MATRIX( outImage );
+    if ( outImage->type.dimen != PS_DIMEN_IMAGE ) {
+        printf( "Error: Resulting image is not PS_DIMEN_IMAGE\n" );
+    } else
+        if ( outImage != tempImage ) {
+            printf( "Error: Return pointer not equal to output argument pointer\n" );
+        }
+    printFooter( stdout, "psMatrix", "Transpose input image into output image", true );
+
+
+    // Test C -  Transpose input image into auto allocated NULL output image
+    printPositiveTestHeader( stdout, "psMatrix", "ranspose input image into auto allocated NULL output image" );
+    psImage *outImageNull = NULL;
+    outImageNull = psMatrixTranspose( outImageNull, inImage );
+    PRINT_MATRIX( outImageNull );
+    printFooter( stdout, "psMatrix", "ranspose input image into auto allocated NULL output image", true );
+
+
+    // Test D - Free images and check for leaks
+    printPositiveTestHeader( stdout, "psMatrix", "Free images and check for leaks" );
+    psFree( inImage );
+    psFree( outImage );
+    psFree( outImageNull );
+    int nLeaks = psMemCheckLeaks( 0, NULL, stdout );
+    if ( nLeaks != 0 ) {
+        printf( "ERROR: Found %d memory leaks\n", nLeaks );
+    }
+    int nBad = psMemCheckCorruption( 0 );
+    if ( nBad ) {
+        printf( "ERROR: Found %d bad memory blocks\n", nBad );
+    }
+    printFooter( stdout, "psMatrix" , "Free images and check for leaks", true );
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix02.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix02.c	(revision 1553)
@@ -0,0 +1,71 @@
+/** @file  tst_psMatrix_02.c
+ *
+ *  @brief Test driver for negative tests for psMatrix transpose function
+ *
+ *  This test driver contains the following tests for psMatrix test point 2:
+ *     A)  Input pointer same as output pointer
+ *     B)  Null input psImage
+ *     C)  Incorrect type for input pointer
+ *     D)  Matrix not square for input pointer
+ *     E)  Incorrect type for output pointer
+ *     F)  Matrix not square for output pointer
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+    psImage *nullImage = NULL;
+    psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *badImage1 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    psImage *badImage2 = (psImage*)psImageAlloc(3, 2, PS_TYPE_F64);
+
+    // Test A - Input pointer same as output pointer
+    printNegativeTestHeader(stdout,"psMatrix", "Input pointer same as output pointer",
+                            "Invalid operation: Pointer to inImage is same as outImage.", 0);
+    psMatrixTranspose(inImage, inImage);
+    printFooter(stdout, "psMatrix", "Input pointer same as output pointer", true);
+
+    // Test B - Null input psImage
+    printNegativeTestHeader(stdout,"psMatrix", "Null input psImage",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psMatrixTranspose(outImage, nullImage);
+    printFooter(stdout, "psMatrix", "Null input psImage", true);
+
+    // Test C - Incorrect type for input pointer
+    printNegativeTestHeader(stdout,"psMatrix", "Incorrect type for input pointer",
+                            "|Invalid operation: inImage not PS_TYPE_F64.", 0);
+    psMatrixTranspose(outImage, badImage1);
+    printFooter(stdout, "psMatrix", "Incorrect type for input pointer", true);
+
+    // Test D - Matrix not square for input pointer
+    printNegativeTestHeader(stdout,"psMatrix", "Matrix not square for input pointer",
+                            "Invalid operation: inImage not square array.", 0);
+    psMatrixTranspose(outImage, badImage2);
+    printFooter(stdout, "psMatrix", "Matrix not square for input pointer", true);
+
+    // Test E - Incorrect type for output pointer
+    printNegativeTestHeader(stdout,"psMatrix", "Incorrect type for output pointer",
+                            "Invalid operation: outImage not PS_TYPE_F64.", 0);
+    psMatrixTranspose(badImage1, inImage);
+    printFooter(stdout, "psMatrix", "Incorrect type for output pointer", true);
+
+    // Test F - Matrix not square for output pointer
+    printNegativeTestHeader(stdout,"psMatrix", "Matrix not square for output pointer",
+                            "Invalid operation: outImage not square array.", 0);
+    psMatrixTranspose(badImage2, inImage);
+    printFooter(stdout, "psMatrix", "Matrix not square for output pointer", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix03.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix03.c	(revision 1553)
@@ -0,0 +1,146 @@
+/** @file  tst_psMatrix_03.c
+ *
+ *  @brief Test driver for psMatrix LU functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 3:
+ *     A)  Create input and output images and vectors
+ *     B)  Calculate LU matrix
+ *     C)  Determine solution to matrix equation
+ *     D)  Free input and output images and vectors
+ *     E)  Attempt to use null image input argument
+ *     F)  Attempt to use null input vector argument
+ *     G)  ttempt to use null LU image argument
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                     \
+for(int i=IMAGE->numRows-1; i>-1; i--) {        \
+    for(int j=0; j<IMAGE->numCols; j++) {       \
+        printf("%f ", IMAGE->data.F64[i][j]);   \
+    }                                           \
+    printf("\n");                               \
+}
+\
+#define PRINT_VECTOR(VECTOR)                    \
+for(int i=0; i<VECTOR->n; i++) {                \
+    printf("%f\n", VECTOR->data.F64[i]);        \
+}
+
+
+int main(int argc,
+         char* argv[])
+{
+    psImage *luImage = NULL;
+    psImage *inImage = NULL;
+    psImage *tempImage = NULL;
+    psVector *tempVector = NULL;
+    psVector *perm = NULL;
+    psVector *outVector = NULL;
+    psVector *inVector = NULL;
+
+
+    // Test A - Create input and output images and vectors
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images and vectors");
+    luImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    perm = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    outVector = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    inVector = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] =  2;
+    inImage->data.F64[0][1] =  4;
+    inImage->data.F64[0][2] =  6;
+    inImage->data.F64[1][0] =  4;
+    inImage->data.F64[1][1] =  5;
+    inImage->data.F64[1][2] =  6;
+    inImage->data.F64[2][0] =  3;
+    inImage->data.F64[2][1] =  1;
+    inImage->data.F64[2][2] = -2;
+    inVector->data.F64[0] = 18.0;
+    inVector->data.F64[1] = 24.0;
+    inVector->data.F64[2] =  4.0;
+    inVector->n = 3;
+    PRINT_MATRIX(inImage);
+    printf("\n");
+    PRINT_VECTOR(inVector);
+    printFooter(stdout, "psMatrix", "Create input and output images and vectors", true);
+
+
+    // Test B - Calculate LU matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Calculate LU matrix");
+    tempImage = luImage;
+    luImage = psMatrixLUD(luImage, perm, inImage);
+    PRINT_MATRIX(luImage);
+    if(luImage->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else
+        if(luImage != tempImage) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Calculate LU matrix", true);
+
+
+    // Test C - Determine solution to matrix equation
+    printPositiveTestHeader(stdout, "psMatrix", "Determine solution to matrix equation");
+    tempVector = outVector;
+    outVector = psMatrixLUSolve(outVector, luImage, inVector, perm);
+    PRINT_VECTOR(outVector);
+    if(outVector->type.dimen != PS_DIMEN_VECTOR) {
+        printf("Error: Resulting image is not PS_DIMEN_VECTOR\n");
+    } else
+        if(outVector != tempVector) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Determine solution to matrix equation", true);
+
+
+    // Test D - Free input and output images and vectors
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images and vectors");
+    psFree(inImage);
+    psFree(luImage);
+    psFree(perm);
+    psFree(outVector);
+    psFree(inVector);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images and vectors", true);
+
+
+    // Test E - Attempt to use null image input argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null image input argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psImage *imageTest = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixLUD(imageTest, NULL, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null image input argument", true);
+
+
+    // Test F - Attempt to use null input vector argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input vector argument",
+                            "Invalid operation: inVector or its data is NULL.", 0);
+    psVector *vectorBad = NULL;
+    psVector *vectorBadOut = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    psVector *permBad = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    psMatrixLUSolve(vectorBadOut, imageTest, vectorBad, permBad);
+    printFooter(stdout, "psMatrix", "Attempt to use null input vector argument", true);
+
+
+    // Test G - Attempt to use null LU image argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null LU image argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psMatrixLUSolve(vectorBadOut, NULL, vectorBad, permBad);
+    printFooter(stdout, "psMatrix", "Attempt to use null LU image argument", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix04.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix04.c	(revision 1553)
@@ -0,0 +1,112 @@
+/** @file  tst_psMatrix_04.c
+ *
+ *  @brief Test driver for psMatrix invert function
+ *
+ *  This test driver contains the following tests for psMatrix test point 4:
+ *     A)  Create input and output images
+ *     B)  Invert matrix and calculate determinant
+ *     C)  Calculate determinant only
+ *     D)  Free input and output images
+ *     E)  Attempt to use null input image argument
+ *     F)  Attempt to use null input float argument
+ *  
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                         \
+for(int i=IMAGE->numRows-1; i>-1; i--) {            \
+    for(int j=0; j<IMAGE->numCols; j++) {           \
+        printf("%f ", IMAGE->data.F64[i][j]);       \
+    }                                               \
+    printf("\n");                                   \
+}
+
+
+int main(int argc,
+         char* argv[])
+{
+    float det = 0.0f;
+    float *det2 = NULL;
+    psImage *outImage = NULL;
+    psImage *inImage = NULL;
+    psImage *tempImage = NULL;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images");
+    outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] =  2;
+    inImage->data.F64[0][1] =  4;
+    inImage->data.F64[0][2] =  3;
+    inImage->data.F64[1][0] =  0;
+    inImage->data.F64[1][1] =  1;
+    inImage->data.F64[1][2] = -1;
+    inImage->data.F64[2][0] =  3;
+    inImage->data.F64[2][1] =  5;
+    inImage->data.F64[2][2] =  7;
+    PRINT_MATRIX(inImage);
+    printFooter(stdout, "psMatrix", "Create input and output images", true);
+
+
+    // Test B - Invert matrix and calculate determinant
+    printPositiveTestHeader(stdout, "psMatrix", "Invert matrix and calculate determinant");
+    tempImage = outImage;
+    outImage = psMatrixInvert(outImage, inImage, &det);
+    PRINT_MATRIX(outImage);
+    printf("\ndet = %f\n", det);
+    if(outImage->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else
+        if(outImage != tempImage) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Invert matrix and calculate determinant", true);
+
+
+    // Test C - Calculate determinant only
+    printPositiveTestHeader(stdout, "psMatrix", "Calculate determinant only");
+    det2 = psMatrixDeterminant(inImage);
+    printf("det = %f\n", *det2);
+    printFooter(stdout, "psMatrix", "Calculate determinant only", true);
+
+
+    // Test D - Free input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images");
+    psFree(outImage);
+    psFree(inImage);
+    psFree(det2);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images", true);
+
+
+    // Test E - Attempt to use null input image argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input image argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psImage *badOutImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixInvert(badOutImage, NULL, &det);
+    printFooter(stdout, "psMatrix", "Attempt to use null input image argument", true);
+
+
+    // Test F - Attempt to use null input float argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input float argument",
+                            "Invalid operation: determinant argument is NULL.", 0);
+    psImage *badInImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixInvert(badOutImage, badInImage, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null input float argument", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix05.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix05.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix05.c	(revision 1553)
@@ -0,0 +1,81 @@
+/** @file  tst_psMatrix_05.c
+*
+*  @brief Test driver for psMatrix multiplication function
+*
+*  This test driver contains the following tests for psMatrix test point 5:
+*     A)  Create input and output images
+*     B)  Multiply images
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-06 22:34:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                         \
+for(int i=0; i<IMAGE->numRows; i++) {           \
+    for(int j=0; j<IMAGE->numCols; j++) {       \
+        printf("%f ", IMAGE->data.F64[i][j]);   \
+    }                                          \
+    printf("\n");                              \
+}
+
+
+int main( int argc,
+          char* argv[] )
+{
+    psImage * outImage = NULL;
+    psImage *inImage1 = NULL;
+    psImage *inImage2 = NULL;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Create input and output images" );
+    outImage = ( psImage* ) psImageAlloc( 2, 2, PS_TYPE_F64 );
+    inImage1 = ( psImage* ) psImageAlloc( 2, 2, PS_TYPE_F64 );
+    inImage2 = ( psImage* ) psImageAlloc( 2, 2, PS_TYPE_F64 );
+    inImage1->data.F64[ 0 ][ 0 ] = 2;
+    inImage1->data.F64[ 0 ][ 1 ] = 3;
+    inImage1->data.F64[ 1 ][ 0 ] = -1;
+    inImage1->data.F64[ 1 ][ 1 ] = 2;
+    inImage2->data.F64[ 0 ][ 0 ] = 4;
+    inImage2->data.F64[ 0 ][ 1 ] = 1;
+    inImage2->data.F64[ 1 ][ 0 ] = 0;
+    inImage2->data.F64[ 1 ][ 1 ] = 6;
+    PRINT_MATRIX( inImage1 );
+    printf( "\n" );
+    PRINT_MATRIX( inImage2 );
+    printFooter( stdout, "psMatrix", "Create input and output images", true );
+
+
+    // Test B - Multiply images
+    printPositiveTestHeader( stdout, "psMatrix", "Multiply images" );
+    psMatrixMultiply( outImage, inImage1, inImage2 );
+    PRINT_MATRIX( outImage );
+    printFooter( stdout, "psMatrix", "Multiply images", true );
+
+
+    // Test C - Free input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Free input and output images" );
+    psFree( outImage );
+    psFree( inImage1 );
+    psFree( inImage2 );
+    int nLeaks = psMemCheckLeaks( 0, NULL, stdout );
+    if ( nLeaks != 0 ) {
+        printf( "ERROR: Found %d memory leaks\n", nLeaks );
+    }
+    int nBad = psMemCheckCorruption( 0 );
+    if ( nBad ) {
+        printf( "ERROR: Found %d bad memory blocks\n", nBad );
+    }
+    printFooter( stdout, "psMatrix" , "Free input and output images", true );
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix06.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix06.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix06.c	(revision 1553)
@@ -0,0 +1,89 @@
+/** @file  tst_psMatrix_06.c
+*
+*  @brief Test driver for psMatrix Eigenvectors function
+*
+*  This test driver contains the following tests for psMatrix test point 6:
+*     A)  Create input and output images
+*     B)  Calculate Eigenvectors
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-08-06 22:34:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                         \
+for(int i=0; i<IMAGE->numRows; i++) {           \
+    for(int j=0; j<IMAGE->numCols; j++) {       \
+        printf("%f ", IMAGE->data.F64[i][j]);   \
+    }                                          \
+    printf("\n");                              \
+}
+
+
+int main( int argc,
+          char* argv[] )
+{
+    psImage * outImage = NULL;
+    psImage *inImage = NULL;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Create input and output images" );
+    outImage = ( psImage* ) psImageAlloc( 4, 4, PS_TYPE_F64 );
+    inImage = ( psImage* ) psImageAlloc( 4, 4, PS_TYPE_F64 );
+
+    inImage->data.F64[ 0 ][ 0 ] = 1. / 1.;
+    inImage->data.F64[ 0 ][ 1 ] = 1. / 2.;
+    inImage->data.F64[ 0 ][ 2 ] = 1. / 3.;
+    inImage->data.F64[ 0 ][ 3 ] = 1. / 4.;
+
+    inImage->data.F64[ 1 ][ 0 ] = 1. / 2.;
+    inImage->data.F64[ 1 ][ 1 ] = 1. / 3.;
+    inImage->data.F64[ 1 ][ 2 ] = 1. / 4.;
+    inImage->data.F64[ 1 ][ 3 ] = 1. / 5.;
+
+    inImage->data.F64[ 2 ][ 0 ] = 1. / 3.;
+    inImage->data.F64[ 2 ][ 1 ] = 1. / 4.;
+    inImage->data.F64[ 2 ][ 2 ] = 1. / 5.;
+    inImage->data.F64[ 2 ][ 3 ] = 1. / 6.;
+
+    inImage->data.F64[ 3 ][ 0 ] = 1. / 4.;
+    inImage->data.F64[ 3 ][ 1 ] = 1. / 5.;
+    inImage->data.F64[ 3 ][ 2 ] = 1. / 6.;
+    inImage->data.F64[ 3 ][ 3 ] = 1. / 7.;
+
+    PRINT_MATRIX( inImage );
+    printFooter( stdout, "psMatrix", "Create input and output images", true );
+
+
+    // Test B - Calculate Eigenvectors
+    printPositiveTestHeader( stdout, "psMatrix", "Calculate Eigenvectors" );
+    psMatrixEigenvectors( outImage, inImage );
+    PRINT_MATRIX( outImage );
+    printFooter( stdout, "psMatrix", "Calculate Eigenvectors", true );
+
+
+    // Test C - Free input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Free input and output images" );
+    psFree( outImage );
+    psFree( inImage );
+    int nLeaks = psMemCheckLeaks( 0, NULL, stdout );
+    if ( nLeaks != 0 ) {
+        printf( "ERROR: Found %d memory leaks\n", nLeaks );
+    }
+    int nBad = psMemCheckCorruption( 0 );
+    if ( nBad ) {
+        printf( "ERROR: Found %d bad memory blocks\n", nBad );
+    }
+    printFooter( stdout, "psMatrix" , "Free input and output images", true );
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrix07.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrix07.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrix07.c	(revision 1553)
@@ -0,0 +1,178 @@
+/** @file  tst_psMatrix_07.c
+ *
+ *  @brief Test driver for psMatrix vector conversion functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 7:
+ *     A)  Create input and output images and vectors
+ *     B)  Convert matrix to PS_DIMEN_VECTOR vector
+ *     C)  Attempt to use null image input argument
+ *     D)  Convert matrix to PS_DIMEN_TRANSV vector
+ *     E)  Improper image size
+ *     F)  Convert PS_DIMEN_VECTOR vector to matrix
+ *     G)  Attempt to use null input vector argument
+ *     H)  Convert PS_DIMEN_TRANSV vector to matrix
+ *     I)  Free input and output images and vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.5 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_MATRIX(IMAGE)                         \
+for(int i=0; i<IMAGE->numRows; i++) {               \
+    for(int j=0; j<IMAGE->numCols; j++) {           \
+        printf("%f ", IMAGE->data.F64[i][j]);       \
+    }                                               \
+    printf("\n");                                   \
+}
+
+#define PRINT_VECTOR(VECTOR)                        \
+for(int i=0; i<VECTOR->n; i++) {                    \
+    printf("%f\n", VECTOR->data.F64[i]);            \
+}
+
+
+int main(int argc,
+         char* argv[])
+{
+    psVector *v1 = NULL;
+    psVector *tempVector = NULL;
+    psImage *tempImage = NULL;
+    psImage *m1 = NULL;
+    psVector *v2 = NULL;
+    psImage *m2 = NULL;
+    psImage *m3 = NULL;
+    psImage *m4 = NULL;
+    psImage *badImage = NULL;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images and vectors");
+    v1 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    m1 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+    v2 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    m2 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+    m3 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+    m4 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+    badImage = (psImage*)psImageAlloc(2, 2, PS_TYPE_F64);
+    m1->data.F64[0][0] = 0.0;
+    m1->data.F64[1][0] = 1.0;
+    m1->data.F64[2][0] = 2.0;
+    v2->data.F64[0] = 0.0;
+    v2->data.F64[1] = 1.0;
+    v2->data.F64[2] = 2.0;
+    v2->n = 3;
+    m4->data.F64[0][0] = 0.0;
+    m4->data.F64[0][1] = 1.0;
+    m4->data.F64[0][2] = 2.0;
+    PRINT_MATRIX(m1);
+    printf("\n");
+    PRINT_MATRIX(m4);
+    printf("\n");
+    PRINT_VECTOR(v2);
+    printFooter(stdout, "psMatrix", "Create input and output images and vectors", true);
+
+
+    // Test B - Convert matrix to PS_DIMEN_VECTOR vector
+    printPositiveTestHeader(stdout, "psMatrix", "Convert matrix to PS_DIMEN_VECTOR vector");
+    tempVector = v1;
+    v1 = psMatrixToVector(v1, m1);
+    PRINT_VECTOR(v1);
+    if(v1->type.dimen != PS_DIMEN_VECTOR) {
+        printf("Error: Resulting image is not PS_DIMEN_VECTOR\n");
+    } else
+        if(v1 != tempVector) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Convert matrix to PS_DIMEN_VECTOR vector", true);
+
+
+    // Test C - Attempt to use null image input argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null image input argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    v1 = psMatrixToVector(v1, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null image input argument", true);
+
+
+    // Test D - Convert matrix to PS_DIMEN_TRANSV vector
+    printPositiveTestHeader(stdout, "psMatrix", "Convert matrix to PS_DIMEN_TRANSV vector");
+    v1->type.dimen = PS_DIMEN_TRANSV;
+    psMatrixToVector(v1, m4);
+    PRINT_VECTOR(v1);
+    if(v1->type.dimen != PS_DIMEN_TRANSV) {
+        printf("Error: Resulting image is not PS_DIMEN_TRANSV\n");
+    } else
+        if(v1 != tempVector) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Convert matrix to PS_DIMEN_TRANSV vector", true);
+
+
+    // Test E - Improper image size
+    printNegativeTestHeader(stdout,"psMatrix", "Improper image size",
+                            "Image does not have dim with 1 col or 1 row: (2 x 2).", 0);
+    psMatrixToVector(v1, badImage);
+    printFooter(stdout, "psMatrix", "Improper image size", true);
+
+
+    // Test F - Convert PS_DIMEN_VECTOR vector to matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Convert PS_DIMEN_VECTOR vector to matrix");
+    tempImage = m2;
+    m2 = psVectorToMatrix(m2, v2);
+    PRINT_MATRIX(m2);
+    if(m2->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else
+        if(m2 != tempImage) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Convert PS_DIMEN_VECTOR vector to matrix", true);
+
+
+    // Test G - Attempt to use null input vector argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input vector argument",
+                            "Invalid operation: inVector or its data is NULL.", 0);
+    psVectorToMatrix(m2, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null input vector argument", true);
+
+
+    // Test H - Convert PS_DIMEN_TRANSV vector to matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Convert PS_DIMEN_TRANSV vector to matrix");
+    v2->type.dimen = PS_DIMEN_TRANSV;
+    tempImage = m3;
+    psVectorToMatrix(m3, v2);
+    PRINT_MATRIX(m3);
+    if(m3->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else
+        if(m3 != tempImage) {
+            printf("Error: Return pointer not equal to output argument pointer\n");
+        }
+    printFooter(stdout, "psMatrix", "Convert PS_DIMEN_TRANSV vector to matrix", true);
+
+
+    // Test I - Free input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images and vectors");
+    psFree(m1);
+    psFree(v1);
+    psFree(m2);
+    psFree(v2);
+    psFree(m3);
+    psFree(m4);
+    psFree(badImage);
+    psMemCheckLeaks(0, NULL, stdout);
+    int nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images and vectors", true);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic01.c	(revision 1553)
@@ -0,0 +1,202 @@
+/** @file  tst_psMatrix_01.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar binary operations including:
+ *     Matrix-matrix with +,-,*,/ with S32, F32, F64, C32
+ *     Matrix-vector with +,-,*,/ with S32, F32, F64, C32
+ *     Matrix-scalar with +,-,*,/ with S32, F32, F64, C32
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+#define PRINT_SCALAR(SCALAR,TYPE)                                                                            \
+if(PS_IS_PSELEMTYPE_COMPLEX(SCALAR->type.type)) {                                                        \
+    printf("%f+%fi ", creal(SCALAR->data.TYPE), cimag(SCALAR->data.TYPE));                               \
+} else if(PS_IS_PSELEMTYPE_INT(SCALAR->type.type)) {                                                     \
+    printf("%d ", (int)SCALAR->data.TYPE);                                                               \
+} else {                                                                                                 \
+    printf("%f ", (double)SCALAR->data.TYPE);                                                            \
+}                                                                                                        \
+printf("\n\n");
+
+#define PRINT_VECTOR(VECTOR,TYPE)                                                                            \
+for(int i=0; i<VECTOR->n; i++) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+        printf("%f+%fi ", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));                     \
+    } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+        printf("%d ", (int)VECTOR->data.TYPE[i]);                                                        \
+    } else {                                                                                             \
+        printf("%f ", (double)VECTOR->data.TYPE[i]);                                                     \
+    }                                                                                                    \
+}                                                                                                        \
+printf("\n\n");
+
+
+#define PRINT_MATRIX(IMAGE,TYPE)                                                                             \
+for(int i=IMAGE->numRows-1; i>-1; i--) {                                                                 \
+    for(int j=0; j<IMAGE->numCols; j++) {                                                                \
+        if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+            printf("%f+%fi ", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j]));             \
+        } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+            printf("%d ", (int)IMAGE->data.TYPE[i][j]);                                                  \
+        } else {                                                                                         \
+            printf("%f ", (double)IMAGE->data.TYPE[i][j]);                                               \
+        }                                                                                                \
+    }                                                                                                    \
+    printf("\n");                                                                                        \
+}                                                                                                        \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                         \
+for(int i=0; i<SIZE; i++) {                                                                              \
+    NAME->data.TYPE[i] = VALUE;                                                                          \
+}                                                                                                        \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                      \
+for(int i=0; i<NAME->numRows; i++) {                                                                     \
+    for(int j=0; j<NAME->numCols; j++) {                                                                 \
+        NAME->data.TYPE[i][j] = VALUE;                                                                   \
+    }                                                                                                    \
+}
+
+
+#define CHECK_MEMORY                                                                                         \
+psMemCheckLeaks(0, NULL, stdout);                                                                        \
+int nBad = psMemCheckCorruption(0);                                                                      \
+if(nBad) {                                                                                               \
+    printf("ERROR: Found %d bad memory blocks\n", nBad);                                                 \
+}
+
+
+int main(int argc, char* argv[])
+{
+
+    // Test matrix-matrix binary operations
+    #define testBinaryOpMM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-matrix psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(inImage,TYPE,VALUE1,NROWS,NCOLS);                                               \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE2,NROWS,NCOLS);                                              \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(inImage,TYPE);                                                                          \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, inImage, #OP, outImage);                                   \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inImage);                                                                                     \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-matrix psBinaryOp", true);              \
+    }
+
+    testBinaryOpMM(+,S32,10,10,3,2);
+    testBinaryOpMM(+,F32,10.0,10.0,3,2);
+    testBinaryOpMM(+,F64,10.0,10.0,3,2);
+    testBinaryOpMM(+,C32,10.0+10.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(-,S32,20,10,3,2);
+    testBinaryOpMM(-,F32,20.0,10.0,3,2);
+    testBinaryOpMM(-,F64,20.0,10.0,3,2);
+    testBinaryOpMM(*,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(*,S32,20,10,3,2);
+    testBinaryOpMM(*,F32,20.0,10.0,3,2);
+    testBinaryOpMM(*,F64,20.0,10.0,3,2);
+    testBinaryOpMM(*,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(/,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(/,S32,20,10,3,2);
+    testBinaryOpMM(/,F32,20.0,10.0,3,2);
+    testBinaryOpMM(/,F64,20.0,10.0,3,2);
+    testBinaryOpMM(/,C32,20.0+20.0i,10.0+10.0i,3,2);
+
+    // Test Matrix-Vector binary operations
+    #define testBinaryOpMV(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-vector psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE1,NROWS,NCOLS);                                              \
+        CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE2,NROWS);                                                   \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        PRINT_VECTOR(inVector,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, outImage, #OP, inVector);                                  \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inVector);                                                                                    \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-vector psBinaryOp", true);              \
+    }
+
+    testBinaryOpMV(+,S32,10,5,3,2);
+    testBinaryOpMV(+,F32,10.0,5.0,3,2);
+    testBinaryOpMV(+,F64,10.0,5.0,3,2);
+    testBinaryOpMV(+,C32,10.0+10.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(-,S32,20,5,3,2);
+    testBinaryOpMV(-,F32,20.0,5.0,3,2);
+    testBinaryOpMV(-,F64,20.0,5.0,3,2);
+    testBinaryOpMV(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(*,S32,20,5,3,2);
+    testBinaryOpMV(*,F32,20.0,5.0,3,2);
+    testBinaryOpMV(*,F64,20.0,5.0,3,2);
+    testBinaryOpMV(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(/,S32,20,5,3,2);
+    testBinaryOpMV(/,F32,20.0,5.0,3,2);
+    testBinaryOpMV(/,F64,20.0,5.0,3,2);
+    testBinaryOpMV(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+
+    // Test Matrix-Scalar binary operations
+    #define testBinaryOpMS(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-scalar psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE1,NROWS,NCOLS);                                              \
+        psScalar *inScalar = (psScalar*)psScalarAlloc(VALUE2,PS_TYPE_##TYPE);                                \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        PRINT_SCALAR(inScalar,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, outImage, #OP, inScalar);                                  \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inScalar);                                                                                    \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-scalar psBinaryOp", true);              \
+    }
+
+    testBinaryOpMS(+,S32,10,5,3,2);
+    testBinaryOpMS(+,F32,10.0,5.0,3,2);
+    testBinaryOpMS(+,F64,10.0,5.0,3,2);
+    testBinaryOpMS(+,C32,10.0+10.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(-,S32,20,5,3,2);
+    testBinaryOpMS(-,F32,20.0,5.0,3,2);
+    testBinaryOpMS(-,F64,20.0,5.0,3,2);
+    testBinaryOpMS(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(*,S32,20,5,3,2);
+    testBinaryOpMS(*,F32,20.0,5.0,3,2);
+    testBinaryOpMS(*,F64,20.0,5.0,3,2);
+    testBinaryOpMS(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(/,S32,20,5,3,2);
+    testBinaryOpMS(/,F32,20.0,5.0,3,2);
+    testBinaryOpMS(/,F64,20.0,5.0,3,2);
+    testBinaryOpMS(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic02.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic02.c	(revision 1553)
@@ -0,0 +1,265 @@
+
+/** @file  tst_psMatrix_02.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar unary operations including:
+ *     Matrix with all math operators with S32, F32, F64, C32
+ *     Vector with all math operators with S32, F32, F64, C32
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-14 01:31:30 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+#include <math.h>
+
+
+#define CHECK_VECTOR(VECTOR,TYPE,TRUTH)                                                                      \
+for(int i=0; i<VECTOR->n; i++) {                                                                             \
+    if(cabs(VECTOR->data.TYPE[i])-cabs(TRUTH) > FLT_EPSILON){                                                \
+        printf("ERROR:Truth and calculated values don't match for vector operation:\n");                     \
+        if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+            printf("Truth: %.2f%+.2fi\n", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));         \
+            printf("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                                  \
+        } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+            printf("Truth: %d\n", (int)(VECTOR->data.TYPE[i]));                                              \
+            printf("Calculated: %d\n", (int)(TRUTH));                                                        \
+        } else {                                                                                             \
+            printf("Truth: %.2f\n", (double)(VECTOR->data.TYPE[i]));                                         \
+            printf("Calculated: %.2f\n", (double)(TRUTH));                                                   \
+        }                                                                                                    \
+    }                                                                                                       \
+}                                                                                                            \
+printf("\n");
+
+
+#define CHECK_MATRIX(IMAGE,TYPE,TRUTH)                                                                       \
+for(int i=IMAGE->numRows-1; i>-1; i--) {                                                                     \
+    for(int j=0; j<IMAGE->numCols; j++) {                                                                    \
+        if(cabs(IMAGE->data.TYPE[i][j])-cabs(TRUTH) > FLT_EPSILON){                                         \
+            printf("ERROR:Truth and calculated values don't match for matrix operation:\n");                 \
+            if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+                printf("Truth: %.2f%+.2fi\n", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j])); \
+                printf("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                              \
+            } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+                printf("Truth: %d\n", (int)(IMAGE->data.TYPE[i][j]));                                        \
+                printf("Calculated: %d\n", (int)(TRUTH));                                                    \
+            } else {                                                                                         \
+                printf("Truth: %.2f\n", (double)(IMAGE->data.TYPE[i][j]));                                   \
+                printf("Calculated: %.2f\n", (double)(TRUTH));                                               \
+            }                                                                                                \
+        }                                                                                                   \
+    }                                                                                                        \
+    printf("\n");                                                                                            \
+}                                                                                                            \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                             \
+for(int i=0; i<SIZE; i++) {                                                                                  \
+    NAME->data.TYPE[i] = VALUE;                                                                              \
+}                                                                                                            \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                          \
+for(int i=0; i<NAME->numRows; i++) {                                                                         \
+    for(int j=0; j<NAME->numCols; j++) {                                                                     \
+        NAME->data.TYPE[i][j] = VALUE;                                                                       \
+    }                                                                                                        \
+}
+
+
+#define CHECK_MEMORY                                                                                         \
+psMemCheckLeaks(0, NULL, stdout);                                                                            \
+int nBad = psMemCheckCorruption(0);                                                                          \
+if(nBad) {                                                                                                   \
+    printf("ERROR: Found %d bad memory blocks\n", nBad);                                                     \
+}
+
+
+int main( int argc, char* argv[] )
+{
+
+    // Test matrix unary operations
+    #define testUnaryOpM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,TRUTH)                                            \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix psUnaryOp");                \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(inImage,TYPE,VALUE1,NROWS,NCOLS);                                               \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE2,NROWS,NCOLS);                                              \
+        outImage = (psImage*)psUnaryOp(outImage, inImage, #OP);                                              \
+        CHECK_MATRIX(outImage,TYPE,TRUTH);                                                                   \
+        psFree(inImage);                                                                                     \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix psUnaryOp", true);                      \
+    }
+
+    testUnaryOpM( abs, S32, -10, 0, 3, 2, 10 );
+    testUnaryOpM( abs, F32, -10.0, 0.0, 3, 2, 10.0 );
+    testUnaryOpM( abs, F64, -10.0, 0.0, 3, 2, 10.0 );
+    testUnaryOpM( abs, C32, -10.0 - 10.0i, 0.0 + 0.0i, 3, 2,10+10i );
+    testUnaryOpM( exp, S32, 10, 0, 3, 2, cexp(10));
+    testUnaryOpM( exp, F32, 10.0, 0.0, 3, 2, cexp(10.0) );
+    testUnaryOpM( exp, F64, 10.0, 0.0, 3, 2, cexp(10.0) );
+    testUnaryOpM( exp, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, cexp(1.0+1.0i) );
+    testUnaryOpM( ln, S32, 10, 0, 3, 2, clog(10) );
+    testUnaryOpM( ln, F32, 10.0, 0.0, 3, 2, clog(10.0) );
+    testUnaryOpM( ln, F64, 10.0, 0.0, 3, 2, clog(10.0) );
+    testUnaryOpM( ln, C32, 10.0 + 10.0i, 0.0 + 0.0i, 3, 2, clog(10.0+10.0i) );
+    testUnaryOpM( ten, S32, 3, 0, 3, 2, 1000 );
+    testUnaryOpM( ten, F32, 3.0, 0.0, 3, 2, 1000 );
+    testUnaryOpM( ten, F64, 3.0, 0.0, 3, 2, 1000 );
+    testUnaryOpM( ten, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, 10.0 );
+    testUnaryOpM( log, S32, 1000, 0, 3, 2, 3 );
+    testUnaryOpM( log, F32, 1000.0, 0.0, 3, 2, 3 );
+    testUnaryOpM( log, F64, 1000.0, 0.0, 3, 2, 3 );
+    testUnaryOpM( log, C32, 1000.0 + 0.0i, 0.0 + 0.0i, 3, 2, 3 );
+    testUnaryOpM( sin, S32, M_PI_2, 0, 3, 2, 1 );
+    testUnaryOpM( sin, F32, M_PI_2, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( sin, F64, M_PI_2, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( sin, C32, M_PI_2 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( dsin, S32, 90, 0, 3, 2 , 1);
+    testUnaryOpM( dsin, F32, 90.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dsin, F64, 90.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dsin, C32, 90.0 + 00.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( cos, S32, 0, 0, 3, 2, 1 );
+    testUnaryOpM( cos, F32, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( cos, F64, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( cos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( dcos, S32, 0, 0, 3, 2, 1 );
+    testUnaryOpM( dcos, F32, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dcos, F64, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dcos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( tan, S32, M_PI_4, 0, 3, 2, 1);
+    testUnaryOpM( tan, F32, M_PI_4, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( tan, F64, M_PI_4, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( tan, C32, M_PI_4 + 0.0i, 0.0 + 0.0i, 3, 2, 1 );
+    testUnaryOpM( dtan, S32, 45, 0, 3, 2, 1 );
+    testUnaryOpM( dtan, F32, 45.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dtan, F64, 45.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dtan, C32, 45.0 + 45.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( asin, S32, 1, 0, 3, 2, M_PI_2);
+    testUnaryOpM( asin, F32, 1.0, 0.0, 3, 2, M_PI_2  );
+    testUnaryOpM( asin, F64, 1.0, 0.0, 3, 2, M_PI_2);
+    testUnaryOpM( asin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, M_PI_2);
+    testUnaryOpM( dasin, S32, 1.0, 0, 3, 2, 90 );
+    testUnaryOpM( dasin, F32, 1.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dasin, F64, 1.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dasin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, 90.0 );
+    testUnaryOpM( acos, S32, 0, 0, 3, 2, M_PI_2);
+    testUnaryOpM( acos, F32, 0.0, 0.0, 3, 2, M_PI_2 );
+    testUnaryOpM( acos, F64, 0.0, 0.0, 3, 2, M_PI_2 );
+    testUnaryOpM( acos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, M_PI_2 );
+    testUnaryOpM( dacos, S32, 0, 0, 3, 2, 90 );
+    testUnaryOpM( dacos, F32, 0.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dacos, F64, 0.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dacos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 90.0 );
+    testUnaryOpM( atan, S32, 1, 0, 3, 2, M_PI_4);
+    testUnaryOpM( atan, F32, 1.0, 0.0, 3, 2, M_PI_4 );
+    testUnaryOpM( atan, F64, 1.0, 0.0, 3, 2, M_PI_4);
+    testUnaryOpM( atan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, M_PI_4);
+    testUnaryOpM( datan, S32, 1, 0, 3, 2, 45 );
+    testUnaryOpM( datan, F32, 1.0, 0.0, 3, 2, 45.0 );
+    testUnaryOpM( datan, F64, 1.0, 0.0, 3, 2, 45.0 );
+    testUnaryOpM( datan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, 45.0 );
+
+
+    // Test vector unary operations
+    #define testUnaryOpV(OP,TYPE,VALUE1,VALUE2,SIZE,TRUTH)                                                   \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test vector psUnaryOp");                \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE1,SIZE);                                                    \
+        CREATE_AND_SET_VECTOR(outVector,TYPE,VALUE2,SIZE);                                                   \
+        outVector = (psVector*)psUnaryOp(outVector, inVector, #OP);                                          \
+        CHECK_VECTOR(outVector,TYPE,TRUTH);                                                                  \
+        psFree(inVector);                                                                                    \
+        psFree(outVector);                                                                                   \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test vector psUnaryOp", true);                      \
+    }
+
+    testUnaryOpV( abs, S32, -10, 0, 3, 10 );
+    testUnaryOpV( abs, F32, -10.0, 0.0, 3, 10.0 );
+    testUnaryOpV( abs, F64, -10.0, 0.0, 3, 10.0 );
+    testUnaryOpV( abs, C32, -10.0 - 10.0i, 0.0 + 0.0i, 3, 10+10i );
+    testUnaryOpV( exp, S32, 10, 0, 3, cexp(10));
+    testUnaryOpV( exp, F32, 10.0, 0.0, 3, cexp(10.0) );
+    testUnaryOpV( exp, F64, 10.0, 0.0, 3, cexp(10.0) );
+    testUnaryOpV( exp, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, cexp(1.0+1.0i) );
+    testUnaryOpV( ln, S32, 10, 0, 3, clog(10) );
+    testUnaryOpV( ln, F32, 10.0, 0.0, 3, clog(10.0) );
+    testUnaryOpV( ln, F64, 10.0, 0.0, 3, clog(10.0) );
+    testUnaryOpV( ln, C32, 10.0 + 10.0i, 0.0 + 0.0i, 3, clog(10.0+10.0i) );
+    testUnaryOpV( ten, S32, 3, 0, 3, 1000 );
+    testUnaryOpV( ten, F32, 3.0, 0.0, 3, 1000 );
+    testUnaryOpV( ten, F64, 3.0, 0.0, 3, 1000 );
+    testUnaryOpV( ten, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 10.0 );
+    testUnaryOpV( log, S32, 1000, 0, 3,  3 );
+    testUnaryOpV( log, F32, 1000.0, 0.0, 3, 3 );
+    testUnaryOpV( log, F64, 1000.0, 0.0, 3, 3 );
+    testUnaryOpV( log, C32, 1000.0 + 0.0i, 0.0 + 0.0i, 3, 3 );
+    testUnaryOpV( sin, S32, M_PI_2, 0, 3, 1 );
+    testUnaryOpV( sin, F32, M_PI_2, 0.0, 3, 1.0 );
+    testUnaryOpV( sin, F64, M_PI_2, 0.0, 3, 1.0 );
+    testUnaryOpV( sin, C32, M_PI_2 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( dsin, S32, 90, 0, 3, 1);
+    testUnaryOpV( dsin, F32, 90.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dsin, F64, 90.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dsin, C32, 90.0 + 00.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( cos, S32, 0, 0, 3, 1 );
+    testUnaryOpV( cos, F32, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( cos, F64, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( cos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( dcos, S32, 0, 0, 3, 1 );
+    testUnaryOpV( dcos, F32, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dcos, F64, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dcos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( tan, S32, M_PI_4, 0, 3, 1);
+    testUnaryOpV( tan, F32, M_PI_4, 0.0, 3, 1.0 );
+    testUnaryOpV( tan, F64, M_PI_4, 0.0, 3, 1.0 );
+    testUnaryOpV( tan, C32, M_PI_4 + 0.0i, 0.0 + 0.0i, 3, 1 );
+    testUnaryOpV( dtan, S32, 45, 0, 3, 1 );
+    testUnaryOpV( dtan, F32, 45.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dtan, F64, 45.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dtan, C32, 45.0 + 45.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( asin, S32, 1, 0, 3, M_PI_2);
+    testUnaryOpV( asin, F32, 1.0, 0.0, 3, M_PI_2  );
+    testUnaryOpV( asin, F64, 1.0, 0.0, 3, M_PI_2);
+    testUnaryOpV( asin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, M_PI_2);
+    testUnaryOpV( dasin, S32, 1.0, 0, 3, 90 );
+    testUnaryOpV( dasin, F32, 1.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dasin, F64, 1.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dasin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 90.0 );
+    testUnaryOpV( acos, S32, 0, 0, 3, M_PI_2);
+    testUnaryOpV( acos, F32, 0.0, 0.0, 3, M_PI_2 );
+    testUnaryOpV( acos, F64, 0.0, 0.0, 3, M_PI_2 );
+    testUnaryOpV( acos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, M_PI_2 );
+    testUnaryOpV( dacos, S32, 0, 0, 3, 90 );
+    testUnaryOpV( dacos, F32, 0.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dacos, F64, 0.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dacos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 90.0 );
+    testUnaryOpV( atan, S32, 1, 0, 3, M_PI_4);
+    testUnaryOpV( atan, F32, 1.0, 0.0, 3, M_PI_4 );
+    testUnaryOpV( atan, F64, 1.0, 0.0, 3, M_PI_4);
+    testUnaryOpV( atan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, M_PI_4);
+    testUnaryOpV( datan, S32, 1, 0, 3, 45 );
+    testUnaryOpV( datan, F32, 1.0, 0.0, 3, 45.0 );
+    testUnaryOpV( datan, F64, 1.0, 0.0, 3, 45.0 );
+    testUnaryOpV( datan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 45.0 );
+
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic03.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMatrixVectorArithmetic03.c	(revision 1553)
@@ -0,0 +1,154 @@
+/** @file  tst_psMatrix_01.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver contains negative tests for psBinaryOp and psUanryOp:
+ *     Check for NULL arguments
+ *     Inconsistent element types
+ *     Inconsistent element count
+ *     Inconsistent dimensionality
+ *     Division by zero
+ *     Attempt to use min with complex numbers
+ *     Attempt to use max with complex numbers
+ *     Invalid operation
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+
+#define PRINT_VECTOR(VECTOR,TYPE)                                                                            \
+for(int i=0; i<VECTOR->n; i++) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+        printf("%f+%fi ", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));                     \
+    } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+        printf("%d ", (int)VECTOR->data.TYPE[i]);                                                        \
+    } else {                                                                                             \
+        printf("%f ", (double)VECTOR->data.TYPE[i]);                                                     \
+    }                                                                                                    \
+}                                                                                                        \
+printf("\n\n");
+
+
+#define PRINT_MATRIX(IMAGE,TYPE)                                                                             \
+for(int i=IMAGE->numRows-1; i>-1; i--) {                                                                 \
+    for(int j=0; j<IMAGE->numCols; j++) {                                                                \
+        if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+            printf("%f+%fi ", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j]));             \
+        } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+            printf("%d ", (int)IMAGE->data.TYPE[i][j]);                                                  \
+        } else {                                                                                         \
+            printf("%f ", (double)IMAGE->data.TYPE[i][j]);                                               \
+        }                                                                                                \
+    }                                                                                                    \
+    printf("\n");                                                                                        \
+}                                                                                                        \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                         \
+for(int i=0; i<SIZE; i++) {                                                                              \
+    NAME->data.TYPE[i] = VALUE;                                                                          \
+}                                                                                                        \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                      \
+for(int i=0; i<NAME->numRows; i++) {                                                                     \
+    for(int j=0; j<NAME->numCols; j++) {                                                                 \
+        NAME->data.TYPE[i][j] = VALUE;                                                                   \
+    }                                                                                                    \
+}
+
+
+int main(int argc, char* argv[])
+{
+    CREATE_AND_SET_IMAGE(image1,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image2,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image3,F32,0,3,3);
+    CREATE_AND_SET_IMAGE(image4,F64,0,2,2);
+    CREATE_AND_SET_IMAGE(image5,C32,1+1i,3,3);
+    CREATE_AND_SET_VECTOR(vector1,F64,0,2);
+    CREATE_AND_SET_VECTOR(vector2,F64,0,3);
+
+
+    // Check for NULL arguments
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Check for NULL arguments",
+                            "Null XXX argument", 0);
+    psBinaryOp(NULL, image1, "+", image2);
+    psBinaryOp(image2, NULL, "+", image2);
+    psBinaryOp(image2, image1, "+", NULL);
+    psBinaryOp(image2, image1, NULL, image2);
+    psUnaryOp(NULL, image1, "sin");
+    psUnaryOp(image2, NULL, "sin");
+    psUnaryOp(image2, image1, NULL);
+    printFooter(stdout, "psBitSet", "Check for NULL arguments", true);
+
+
+    // Inconsistent element types
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Inconsistent element types",
+                            "Element types for arguments inconsistent", 0);
+    psBinaryOp(image2, image3, "+", image2);
+    psUnaryOp(image2, image3, "sin");
+    printFooter(stdout, "psBitSet", "Inconsistent element types", true);
+
+
+    // Inconsistent element count
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Inconsistent element count",
+                            "Inconsistent element count", 0);
+    psBinaryOp(image2, image4, "+", image2);
+    psUnaryOp(image2, image4, "sin");
+    psBinaryOp(image2, vector1, "+", image2);
+    vector1->type.dimen = PS_DIMEN_TRANSV;
+    psBinaryOp(image2, vector1, "+", image2);
+    printFooter(stdout, "psBitSet", "Inconsistent element count", true);
+
+
+    // Inconsistent dimensionality
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Inconsistent dimensionality",
+                            "Dimensionality for arguments inconsistent", 0);
+    psUnaryOp(image2, vector2, "sin");
+    printFooter(stdout, "psBitSet", "Inconsistent dimensionality", true);
+
+
+    // Division by zero
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Divide by zero",
+                            "Divide by zero", 0);
+    psBinaryOp(image1, image1, "/", image2);
+    printFooter(stdout, "psBitSet", "Division by zero", true);
+
+
+    // Attempt to use min with complex numbers
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Use min with complex numbers",
+                            "Minimum operation not supported for complex numbers", 0);
+    psBinaryOp(image5, image5, "min", image5);
+    printFooter(stdout, "psBitSet", "Use min with complex numbers", true);
+
+
+    // Attempt to use max with complex numbers
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Use max with complex numbers",
+                            "Maximum operation not supported for complex numbers", 0);
+    psBinaryOp(image5, image5, "max", image5);
+    printFooter(stdout, "psBitSet", "Use max with complex numbers", true);
+
+
+    // Invalid operation
+    printNegativeTestHeader(stdout,"psMatrixVectorArithmetic", "Invalid operation",
+                            "Invalid operation", 0);
+    psBinaryOp(image1, image1, "yarg", image2);
+    psUnaryOp(image2, image1, "yarg");
+    printFooter(stdout, "psBitSet", "Invalid operation", true);
+
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMinimize00.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMinimize00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMinimize00.c	(revision 1553)
@@ -0,0 +1,166 @@
+/*****************************************************************************
+    This routine must ensure that the psMinimizeChi2 function correctly
+    minimizes an arbitrary function.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include <math.h>
+#define NUM_DATA 10
+#define DATA_WIDTH 2
+#define NUM_PARAMS 4
+
+float myFunc(const psVector *restrict myData,
+             const psVector *restrict myParams)
+{
+    float x = myData->data.F32[0];
+    float y = myData->data.F32[1];
+    float A = myParams->data.F32[0];
+    float B = myParams->data.F32[1];
+    float C = myParams->data.F32[2];
+    float D = myParams->data.F32[3];
+    float tmp = 0.0;
+
+    tmp = (A * x) + (B*x*x) + (C*y*y) + (D*x*x*y);
+    //    printf("--------- myFunc((%.1f %.1f) %.1f %.1f %.1f %.1f) is %.1f ---------\n",
+    //           x, y, A, B, C, D, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv(const psVector *restrict myData,
+                  const psVector *restrict myParams,
+                  int whichParamDeriv)
+{
+    float x = myData->data.F32[0];
+    float y = myData->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = 1.0;
+        tmp = x;
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = x;
+            tmp = x*x;
+        } else
+            if (whichParamDeriv == 2) {
+                tmp = y;
+                tmp = y*y;
+            } else
+                if (whichParamDeriv == 3) {
+                    tmp = x * x * y;
+                }
+
+    //    printf("--------- myFuncDeriv((%.1f %.1f) %.1f %.1f %.1f %.1f (%d)) is %.1f ---------\n",
+    //            x, y, myParams->data.F32[0], myParams->data.F32[1],
+    //            myParams->data.F32[2], myParams->data.F32[3], whichParamDeriv, tmp);
+    return(tmp);
+}
+
+
+int main()
+{
+    psImage *domain = NULL;
+    psVector *data = NULL;
+    psVector *errors = NULL;
+    psVector *initialGuess = NULL;
+    psVector *paramMask = NULL;
+    psVector *tmpVecPtr = NULL;
+    float chiSq = 0.0;
+    int i = 0;
+    int j = 0;
+    int currentId = psMemGetId();
+    int testStatus = true;
+    int memLeaks = 0;
+    psVector *theParams = NULL;
+
+    domain = psImageAlloc(DATA_WIDTH, NUM_DATA, PS_TYPE_F32);
+    data = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+    errors = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+    initialGuess = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    paramMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    tmpVecPtr = psVectorAlloc(DATA_WIDTH, PS_TYPE_F32);
+
+
+    //--------- myFunc((0.0 1.0) -8.6 -7.6 14.6 5.0) is 6.0 ---------
+
+    initialGuess->data.F32[0] = -8.6;
+    initialGuess->data.F32[1] = -7.6;
+    initialGuess->data.F32[2] = 14.6;
+    initialGuess->data.F32[3] = 5.0;
+
+    // Build the data.
+    initialGuess->data.F32[0] = 2.0;
+    initialGuess->data.F32[1] = 3.0;
+    initialGuess->data.F32[2] = 4.0;
+    initialGuess->data.F32[3] = 5.0;
+
+
+    for (i = 0; i<NUM_DATA; i++) {
+        for (j=0; j<DATA_WIDTH; j++) {
+            domain->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    for (i = 0; i<NUM_DATA; i++) {
+        errors->data.F32[i] = 0.1;
+    }
+
+    //    printf("========== Setting Data Values ==========\n");
+    for (i = 0; i<NUM_DATA; i++) {
+        for (j=0; j<DATA_WIDTH; j++) {
+            tmpVecPtr->data.F32[j] = domain->data.F32[i][j];
+        }
+        data->data.F32[i] = myFunc(tmpVecPtr, initialGuess);
+    }
+    //    printf("=========================================\n");
+
+    for (i=0;i<NUM_PARAMS;i++) {
+        initialGuess->data.F32[i]+= 1.0;
+    }
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimizeChi2(): no masks");
+
+    theParams = psMinimizeChi2(myFunc,
+                               myFuncDeriv,
+                               domain,
+                               data,
+                               errors,
+                               initialGuess,
+                               NULL,
+                               &chiSq);
+    for (i=0;i<NUM_PARAMS;i++) {
+        printf("theParams[%d] is %.1f\n", i, theParams->data.F32[i]);
+    }
+
+    printf("chiSq is %f\n", chiSq);
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimizeChi2(): no masks",
+                testStatus);
+
+
+    psMemCheckCorruption(1);
+    psFree(domain);
+    psFree(data);
+    psFree(errors);
+    psFree(initialGuess);
+    psFree(paramMask);
+    psFree(tmpVecPtr);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMinimize01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMinimize01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMinimize01.c	(revision 1553)
@@ -0,0 +1,172 @@
+/*****************************************************************************
+    This routine must ensure that the psMinimizeChi2 function correctly
+    minimizes an arbitrary function.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include <math.h>
+#define NUM_DATA 40
+#define DATA_WIDTH 1
+#define NUM_PARAMS 3
+
+// The function is f(x) = (A * e^(lambda x)) + b
+
+float myFunc(const psVector *restrict myData,
+             const psVector *restrict myParams)
+{
+    float x = myData->data.F32[0];
+    float A = myParams->data.F32[0];
+    float lambda = myParams->data.F32[1];
+    float b = myParams->data.F32[2];
+    float tmp = A * exp(-lambda * x) + b;
+
+    //    printf("--------- myFunc((%.1f) %.1f %.1f %.1f) is %.1f ---------\n",
+    //           x, A, lambda, b, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv(const psVector *restrict myData,
+                  const psVector *restrict myParams,
+                  int whichParamDeriv)
+{
+    float x = myData->data.F32[0];
+    float A = myParams->data.F32[0];
+    float lambda = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = exp(-lambda * x);
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = -x * A * exp(-lambda * x);
+        } else
+            if (whichParamDeriv == 2) {
+                tmp = 1.0;
+            }
+
+    //    printf("--------- myFuncDeriv((%.1f) %.1f %.1f %.1f, %d) is %.1f ---------\n",
+    //           x, A, lambda, myParams->data.F32[2], whichParamDeriv, tmp);
+
+    return(tmp);
+}
+
+int main()
+{
+    psImage *domain = NULL;
+    psVector *data = NULL;
+    psVector *errors = NULL;
+    psVector *initialGuess = NULL;
+    psVector *paramMask = NULL;
+    psVector *tmpVecPtr = NULL;
+    float chiSq = 0.0;
+    int i = 0;
+    psVector *theParams = NULL;
+    int currentId = psMemGetId();
+    int testStatus = true;
+    int memLeaks = 0;
+
+    domain = psImageAlloc(DATA_WIDTH, NUM_DATA, PS_TYPE_F32);
+    data = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+    errors = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+    initialGuess = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    paramMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    tmpVecPtr = psVectorAlloc(DATA_WIDTH, PS_TYPE_F32);
+
+    // Build the data.
+    initialGuess->data.F32[0] = 1.0;
+    initialGuess->data.F32[1] = 0.0;
+    initialGuess->data.F32[2] = 0.0;
+
+    for (i = 0; i<NUM_DATA; i++) {
+        errors->data.F32[i] = 0.1;
+        domain->data.F32[i][0] = (float) i;
+    }
+
+    printf("========== Setting Data Values ==========\n");
+    data->data.F32[0] = 6.013392;
+    data->data.F32[1] = 5.515377;
+    data->data.F32[2] = 5.261095;
+    data->data.F32[3] = 4.777455;
+    data->data.F32[4] = 4.451353;
+    data->data.F32[5] = 3.904903;
+    data->data.F32[6] = 3.504387;
+    data->data.F32[7] = 3.414999;
+    data->data.F32[8] = 3.242736;
+    data->data.F32[9] = 3.122204;
+    data->data.F32[10] = 2.837632;
+    data->data.F32[11] = 2.534700;
+    data->data.F32[12] = 2.439173;
+    data->data.F32[13] = 2.380830;
+    data->data.F32[14] = 2.316090;
+    data->data.F32[15] = 2.060826;
+    data->data.F32[16] = 1.945679;
+    data->data.F32[17] = 1.914126;
+    data->data.F32[18] = 1.759509;
+    data->data.F32[19] = 1.665067;
+    data->data.F32[20] = 1.737926;
+    data->data.F32[21] = 1.575523;
+    data->data.F32[22] = 1.525066;
+    data->data.F32[23] = 1.409607;
+    data->data.F32[24] = 1.395209;
+    data->data.F32[25] = 1.416887;
+    data->data.F32[26] = 1.376042;
+    data->data.F32[27] = 1.260955;
+    data->data.F32[28] = 1.289627;
+    data->data.F32[29] = 1.422672;
+    data->data.F32[30] = 1.228287;
+    data->data.F32[31] = 1.199176;
+    data->data.F32[32] = 1.189989;
+    data->data.F32[33] = 0.930076;
+    data->data.F32[34] = 1.224608;
+    data->data.F32[35] = 1.147376;
+    data->data.F32[36] = 1.114001;
+    data->data.F32[37] = 1.195118;
+    data->data.F32[38] = 1.269581;
+    data->data.F32[39] = 1.061982;
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimizeChi2(): no masks");
+
+    theParams = psMinimizeChi2(myFunc,
+                               myFuncDeriv,
+                               domain,
+                               data,
+                               errors,
+                               initialGuess,
+                               NULL,
+                               &chiSq);
+
+    for (i=0;i<NUM_PARAMS;i++) {
+        printf("theParams[%d] is %.1f\n", i, theParams->data.F32[i]);
+    }
+    printf("chiSq is %f\n", chiSq);
+
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimizeChi2(): no masks",
+                testStatus);
+    psMemCheckCorruption(1);
+    psFree(domain);
+    psFree(data);
+    psFree(errors);
+    psFree(initialGuess);
+    psFree(paramMask);
+    psFree(tmpVecPtr);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMinimize02.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMinimize02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMinimize02.c	(revision 1553)
@@ -0,0 +1,168 @@
+/*****************************************************************************
+    This routine must ensure that the psMinimize function correctly
+    minimizes an arbitrary function.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include <math.h>
+#define DATA_WIDTH 2
+#define NUM_PARAMS 2
+
+float myFunc0(const psVector *restrict myParams,
+              const psVector *restrict myCoords)
+{
+    float P0 = myCoords->data.F32[0];
+    float P1 = myCoords->data.F32[1];
+    float x = myParams->data.F32[0];
+    float y = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    tmp = 10.0 * (x - P0) * (x - P0) + 20.0 * (y - P1) * (y - P1) + 30.0;
+    //    printf("--------- myFunc((%.1f %.1f) %.1f %.1f) is %.1f ---------\n",
+    //    printf("--------- myFunc() params: (%.1f %.1f) coords: (%.1f %.1f) is %.1f ---------\n",
+    //           x, y, P0, P1, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv0(const psVector *restrict myParams,
+                   const psVector *restrict myCoords,
+                   int whichParamDeriv)
+{
+    float P0 = myCoords->data.F32[0];
+    float P1 = myCoords->data.F32[1];
+    float x = myParams->data.F32[0];
+    float y = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = 20.0 * (x - P0);
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = 40.0 * (y - P1);
+        }
+
+    //    printf("--------- myFuncDeriv((%.1f %.1f) %.1f %.1f (%d)) is %.1f ---------\n",
+    //            x, y, myParams->data.F32[0], myParams->data.F32[1], whichParamDeriv, tmp);
+    return(tmp);
+}
+
+
+float myFunc(const psVector *restrict myParams,
+             const psVector *restrict myCoords)
+{
+    float x = myCoords->data.F32[0];
+    float y = myCoords->data.F32[1];
+    float A = myParams->data.F32[0];
+    float B = myParams->data.F32[1];
+    float C = myParams->data.F32[2];
+    float D = myParams->data.F32[3];
+    float tmp = 0.0;
+
+    tmp = (A * x) + (B*x*x) + (C*y*y) + (D*x*x*y);
+    printf("--------- myFunc((%.1f %.1f) %.1f %.1f %.1f %.1f) is %.1f ---------\n",
+           x, y, A, B, C, D, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv(const psVector *restrict myParams,
+                  const psVector *restrict myCoords,
+                  int whichParamDeriv)
+{
+    float x = myCoords->data.F32[0];
+    float y = myCoords->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = 1.0;
+        tmp = x;
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = x;
+            tmp = x*x;
+        } else
+            if (whichParamDeriv == 2) {
+                tmp = y;
+                tmp = y*y;
+            } else
+                if (whichParamDeriv == 3) {
+                    tmp = x * x * y;
+                }
+
+    printf("--------- myFuncDeriv((%.1f %.1f) %.1f %.1f %.1f %.1f (%d)) is %.1f ---------\n",
+           x, y, myParams->data.F32[0], myParams->data.F32[1],
+           myParams->data.F32[2], myParams->data.F32[3], whichParamDeriv, tmp);
+    return(tmp);
+}
+
+
+int main()
+{
+    psVector *initialGuess = NULL;
+    psVector *paramMask = NULL;
+    psVector *coord = NULL;
+    int i = 0;
+    int currentId = psMemGetId();
+    int testStatus = true;
+    int memLeaks = 0;
+    psVector *theParams = NULL;
+
+    initialGuess = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    paramMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    coord = psVectorAlloc(DATA_WIDTH, PS_TYPE_F32);
+
+
+    //--------- myFunc((0.0 1.0) -8.6 -7.6 14.6 5.0) is 6.0 ---------
+
+    // Build the data.
+    initialGuess->data.F32[0] = 5.0;
+    initialGuess->data.F32[1] = 7.0;
+
+    for (i=0;i<DATA_WIDTH;i++) {
+        coord->data.F32[i] = (float) i;
+    }
+    coord->data.F32[0] = 1.0;
+    coord->data.F32[1] = 2.0;
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimize(): no masks");
+
+    for (i=0;i<NUM_PARAMS;i++)
+        printf("Initial parameter %d is: %.1f\n", i, initialGuess->data.F32[i]);
+
+    theParams = psMinimize(initialGuess,
+                           myFunc0,
+                           myFuncDeriv0,
+                           coord,
+                           NULL);
+
+    for (i=0;i<NUM_PARAMS;i++)
+        printf("Parameter %d is: %.1f\n", i, theParams->data.F32[i]);
+
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimize(): no masks",
+                testStatus);
+
+    psMemCheckCorruption(1);
+    psFree(initialGuess);
+    psFree(paramMask);
+    psFree(coord);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMinimize03.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMinimize03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMinimize03.c	(revision 1553)
@@ -0,0 +1,172 @@
+/*****************************************************************************
+    This routine must ensure that the psMinimize function correctly
+    minimizes an arbitrary function.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include <math.h>
+#define DATA_WIDTH 2
+#define NUM_PARAMS 4
+
+float myFunc0(const psVector *restrict myParams,
+              const psVector *restrict myCoords)
+{
+    float P0 = myCoords->data.F32[0];
+    float P1 = myCoords->data.F32[1];
+    float x = myParams->data.F32[0];
+    float y = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    tmp = 10.0 * (x - P0) * (x - P0) + 20.0 * (y - P1) * (y - P1) + 30.0;
+    //    printf("--------- myFunc((%.1f %.1f) %.1f %.1f) is %.1f ---------\n",
+    //    printf("--------- myFunc() params: (%.1f %.1f) coords: (%.1f %.1f) is %.1f ---------\n",
+    //           x, y, P0, P1, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv0(const psVector *restrict myParams,
+                   const psVector *restrict myCoords,
+                   int whichParamDeriv)
+{
+    float P0 = myCoords->data.F32[0];
+    float P1 = myCoords->data.F32[1];
+    float x = myParams->data.F32[0];
+    float y = myParams->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = 20.0 * (x - P0);
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = 40.0 * (y - P1);
+        }
+
+    //    printf("--------- myFuncDeriv((%.1f %.1f) %.1f %.1f (%d)) is %.1f ---------\n",
+    //            x, y, myParams->data.F32[0], myParams->data.F32[1], whichParamDeriv, tmp);
+    return(tmp);
+}
+
+
+float myFunc(const psVector *restrict myParams,
+             const psVector *restrict myCoords)
+{
+    float x = myCoords->data.F32[0];
+    float y = myCoords->data.F32[1];
+    float A = myParams->data.F32[0];
+    float B = myParams->data.F32[1];
+    float C = myParams->data.F32[2];
+    float D = myParams->data.F32[3];
+    float tmp = 0.0;
+
+    tmp = (A * x) + (B*x*x) + (C*y*y) + (D*x*x*y);
+    printf("-- myFunc() params: (%.1f %.1f %.1f %.1f) coords: (%.1f %.1f) is %.1f ---------\n",
+           A, B, C, D, x, y, tmp);
+
+    return(tmp);
+}
+
+float myFuncDeriv(const psVector *restrict myParams,
+                  const psVector *restrict myCoords,
+                  int whichParamDeriv)
+{
+    float x = myCoords->data.F32[0];
+    float y = myCoords->data.F32[1];
+    float tmp = 0.0;
+
+    if (whichParamDeriv == 0) {
+        tmp = 1.0;
+        tmp = x;
+    } else
+        if (whichParamDeriv == 1) {
+            tmp = x;
+            tmp = x*x;
+        } else
+            if (whichParamDeriv == 2) {
+                tmp = y;
+                tmp = y*y;
+            } else
+                if (whichParamDeriv == 3) {
+                    tmp = x * x * y;
+                }
+
+    printf("--------- myFuncDeriv((%.1f %.1f) %.1f %.1f %.1f %.1f (%d)) is %.1f ---------\n",
+           x, y, myParams->data.F32[0], myParams->data.F32[1],
+           myParams->data.F32[2], myParams->data.F32[3], whichParamDeriv, tmp);
+    return(tmp);
+}
+
+
+int main()
+{
+    psVector *initialGuess = NULL;
+    psVector *paramMask = NULL;
+    psVector *coord = NULL;
+    int i = 0;
+    int currentId = psMemGetId();
+    int testStatus = true;
+    int memLeaks = 0;
+    psVector *theParams = NULL;
+
+    initialGuess = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    paramMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    coord = psVectorAlloc(DATA_WIDTH, PS_TYPE_F32);
+
+
+    //--------- myFunc((0.0 1.0) -8.6 -7.6 14.6 5.0) is 6.0 ---------
+
+    // Build the data.
+    initialGuess->data.F32[0] = 2.0;
+    initialGuess->data.F32[1] = 3.0;
+    initialGuess->data.F32[2] = 4.0;
+    initialGuess->data.F32[3] = 5.0;
+
+    for (i=0;i<DATA_WIDTH;i++) {
+        coord->data.F32[i] = (float) i;
+    }
+    coord->data.F32[0] = 1.0;
+    coord->data.F32[1] = 2.0;
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimize(): no masks");
+
+    for (i=0;i<NUM_PARAMS;i++)
+        printf("Initial parameter %d is: %.1f\n", i, initialGuess->data.F32[i]);
+
+    theParams = psMinimize(initialGuess,
+                           myFunc,
+                           myFuncDeriv,
+                           coord,
+                           NULL);
+
+    for (i=0;i<NUM_PARAMS;i++)
+        printf("Parameter %d is: %.1f\n", i, theParams->data.F32[i]);
+
+    printf("Function is %.1f\n", myFunc(theParams, coord));
+
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimize(): no masks",
+                testStatus);
+
+    psMemCheckCorruption(1);
+    psFree(initialGuess);
+    psFree(paramMask);
+    psFree(coord);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psMinimize04.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psMinimize04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psMinimize04.c	(revision 1553)
@@ -0,0 +1,79 @@
+/*****************************************************************************
+    This routine must ensure that the psVectorFitPolynomial1D works correctly.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psFunctions.h"
+#include "psMinimize.h"
+#include <math.h>
+#define NUM_DATA 10
+#define POLY_ORDER 2
+
+double setData(double A,
+               double B,
+               double C,
+               double x)
+{
+    return(A + (B * x) + (C * x * x));
+}
+
+int main()
+{
+    psPolynomial1D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *yErr = NULL;
+    int i = 0;
+    int currentId = psMemGetId();
+    int testStatus = true;
+    int memLeaks = 0;
+
+    myPoly = psPolynomial1DAlloc(POLY_ORDER+1);
+    x = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    y = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    yErr = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+
+    for (i=0;i<NUM_DATA;i++) {
+        x->data.F64[i] = (double) i;
+        y->data.F64[i] = setData(2.0, 3.0, 2.0, x->data.F64[i]);
+        yErr->data.F64[i] = 0.1;
+        printf("Original data %d: (%.1f %.1f)\n", i, x->data.F64[i], y->data.F64[i]);
+    }
+
+    psVectorFitPolynomial1D(myPoly, x, y, yErr);
+
+    for (i=0;i<POLY_ORDER+1;i++) {
+        printf("Polynomial coefficient %d is %0.1f\n", i, myPoly->coeff[i]);
+    }
+
+    for (i=0;i<NUM_DATA;i++) {
+        printf("Fitted data %d: (%.1f %.1f)\n", i, x->data.F64[i],
+               setData(myPoly->coeff[0], myPoly->coeff[1],
+                       myPoly->coeff[2], x->data.F64[i]));
+    }
+
+
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimize(): no masks",
+                testStatus);
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats00.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats00.c	(revision 1553)
@@ -0,0 +1,204 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_MEAN is correctly computed
+    by the procedure psArrayStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N 10
+
+int main()
+{
+    psStats *myStats    = NULL;
+    psStats *myStats2    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float mean          = 0.0;
+    float realMeanNoMask   = 0.0;
+    float realMeanWithMask = 0.0;
+    int count           = 0;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    mean = 0.0;
+    realMeanWithMask = 0.0;
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        realMeanNoMask+= myVector->data.F32[i];
+
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            realMeanWithMask+= myVector->data.F32[i];
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+
+    realMeanNoMask /= (float) N;
+    realMeanWithMask /= (float) count;
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEAN: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+    mean = myStats->sampleMean;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected mean was %f; the calculated mean was %f\n", realMeanNoMask, mean);
+    if (mean == realMeanNoMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_MEAN: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=1.                             */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEAN: with vector mask=1");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    mean = myStats->sampleMean;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
+    if (mean == realMeanWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_MEAN: with vector mask=1",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=2.                             */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEAN: with vector mask=2");
+
+    // Set the mask vector and calculate the expected maximum.
+    // Set the mask vector.
+    for (i=0;i<N;i++) {
+        if (maskVector->data.U8[i] == 1) {
+            maskVector->data.U8[i] = 2;
+        }
+    }
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 2);
+    mean = myStats->sampleMean;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
+    if (mean == realMeanWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_MEAN: with vector mask=2",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=3.                             */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEAN: with vector mask=3");
+
+    // Set the mask vector and calculate the expected maximum.
+    // Set the mask vector.
+    for (i=0;i<N;i++) {
+        if (maskVector->data.U8[i] == 2) {
+            maskVector->data.U8[i] = 3;
+        }
+    }
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 3);
+    mean = myStats->sampleMean;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected mean was %f; the calculated mean was %f\n", realMeanWithMask, mean);
+    if (mean == realMeanWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_MEAN: with vector mask=3",
+                testStatus);
+    /*************************************************************************/
+    /*  Call psVectorStats() with NULL inputs.                               */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEAN: NULL inputs");
+
+    myStats = psVectorStats(myStats, NULL, NULL, 0);
+    myStats2 = psVectorStats(NULL, myVector, NULL, 0);
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_MEAN: NULL inputs",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats01.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats01.c	(revision 1553)
@@ -0,0 +1,125 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_MAX is correctly computed
+    by the procedure psVectorStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N 10
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float max           = 0.0;
+    float realMaxNoMask   = 0.0;
+    float realMaxWithMask = 0.0;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (myVector->data.F32[i] > realMaxNoMask) {
+            realMaxNoMask = myVector->data.F32[i];
+        }
+
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+
+            if (myVector->data.F32[i] > realMaxWithMask) {
+                realMaxWithMask = myVector->data.F32[i];
+            }
+        } else {
+            maskVector->data.U8[i] = 1;
+            printf("Masking element %d\n", i);
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_MAX: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+    max = myStats->max;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected max was %f; the calculated max was %f\n", realMaxNoMask, max);
+    if (max == realMaxNoMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_MAX: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_MAX: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    max = myStats->max;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected max was %f; the calculated max was %f\n", realMaxWithMask, max);
+    if (max == realMaxWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_MAX: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats02.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats02.c	(revision 1553)
@@ -0,0 +1,125 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_MIN is correctly computed
+    by the procedure psVectorStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N 10
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float min           = 1e99;
+    float realMinNoMask   = 1e99;
+    float realMinWithMask = 1e99;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MIN);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected minimum.
+    for (i=0;i<N;i++) {
+        if (myVector->data.F32[i] < realMinNoMask) {
+            realMinNoMask = myVector->data.F32[i];
+        }
+
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 1;
+        } else {
+            maskVector->data.U8[i] = 0;
+            if (myVector->data.F32[i] < realMinWithMask) {
+                realMinWithMask = myVector->data.F32[i];
+            }
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_MIN: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+    min = myStats->min;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected min was %f; the calculated min was %f\n",
+           realMinNoMask, min);
+    if (min == realMinNoMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_MIN: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_MIN: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    min = myStats->min;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected min was %f; the calculated min was %f\n",
+           realMinWithMask, min);
+    if (min == realMinWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_MIN: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats03.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats03.c	(revision 1553)
@@ -0,0 +1,120 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_MEDIAN is correctly computed
+    by the procedure psVectorStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N1 1029   // This should be an odd number.
+#define N ((4 * N1) + 1)
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float median        = 1e99;
+    float realMedianWithMask = (float) (N-3)/4;
+    float realMedianNoMask = (float) (N-1)/2;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected median.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEDIAN: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+    median = myStats->sampleMedian;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected median was %f.  The calculated median was %f.\n",
+           realMedianNoMask, median);
+    if (median == realMedianNoMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "PS_STAT_SAMPLE_MEDIAN: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEDIAN: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    median = myStats->sampleMedian;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected median was %f.  The calculated median was %f.\n",
+           realMedianWithMask, median);
+    if (median == realMedianWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "PS_STAT_SAMPLE_MEDIAN: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats04.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats04.c	(revision 1553)
@@ -0,0 +1,82 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_NVALUES is correctly computed
+    by the procedure psVectorStats().
+ 
+    Note: The NVALUES stat was removed from the IfA requirements spec.  So,
+    this test is no longer in use.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N1 1029
+#define N ((4 * N1) + 1)
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_NVALUES);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_NVALUES");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected nvalues was %d.  The calculated nvalues was %d.\n",
+           N, myStats->nValues);
+    if (myStats->nValues == N) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected nvalues was %d.  The calculated nvalues was %d.\n",
+           N/2, myStats->nValues);
+    if (myStats->nValues == N/2) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+    }
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashAlloc()",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats05.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats05.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats05.c	(revision 1553)
@@ -0,0 +1,76 @@
+/*****************************************************************************
+    This routine must ensure that the psStats structure is correctly
+    allocated and deallocated by the procedure psArrayStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#define MISC_FLOAT_NUMBER 345.0
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Allocate the psStats structure.");
+
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myStats->sampleMean = MISC_FLOAT_NUMBER;
+    myStats->sampleMedian = MISC_FLOAT_NUMBER;
+    myStats->sampleStdev = MISC_FLOAT_NUMBER;
+    myStats->sampleUQ = MISC_FLOAT_NUMBER;
+    myStats->sampleLQ = MISC_FLOAT_NUMBER;
+    myStats->sampleLimit = MISC_FLOAT_NUMBER;
+    myStats->robustMean = MISC_FLOAT_NUMBER;
+    myStats->robustMedian = MISC_FLOAT_NUMBER;
+    myStats->robustMode = MISC_FLOAT_NUMBER;
+    myStats->robustStdev = MISC_FLOAT_NUMBER;
+    myStats->robustUQ = MISC_FLOAT_NUMBER;
+    myStats->robustLQ = MISC_FLOAT_NUMBER;
+    myStats->robustN50 = MISC_FLOAT_NUMBER;
+    myStats->robustNfit = MISC_FLOAT_NUMBER;
+    myStats->clippedMean = MISC_FLOAT_NUMBER;
+    myStats->clippedStdev = MISC_FLOAT_NUMBER;
+    myStats->clipSigma = MISC_FLOAT_NUMBER;
+    myStats->clipIter = MISC_FLOAT_NUMBER;
+    myStats->min = MISC_FLOAT_NUMBER;
+    myStats->max = MISC_FLOAT_NUMBER;
+    myStats->binsize = MISC_FLOAT_NUMBER;
+    myStats->options = 0x0;
+
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate the psStats structure.",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psStats structure.");
+    psFree(myStats);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psStats structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats06.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats06.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats06.c	(revision 1553)
@@ -0,0 +1,128 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_STDEV is correctly computed
+    by the procedure psArrayStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define N 15
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float stdev         = 0.0;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    float realStdevNoMask   = 4.472136;
+    float realStdevWithMask = 2.160247;
+    int count           = 0;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_STDEV);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    stdev = 0.0;
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_STDEV: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+    stdev = myStats->sampleStdev;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected stdev was %f; the calculated stdev was %f\n",
+           realStdevNoMask, stdev);
+    if (fabs(stdev - realStdevNoMask) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_STDEV: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_STDEV: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+    stdev = myStats->sampleStdev;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected stdev was %f; the calculated stdev was %f\n",
+           realStdevWithMask, stdev);
+    if (fabs(stdev - realStdevWithMask) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_STDEV: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats07.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats07.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats07.c	(revision 1553)
@@ -0,0 +1,415 @@
+/*****************************************************************************
+   This routine must ensure that PS_STAT_ROBUST_QUARTILE is correctly computed
+   by the procedure psArrayStats().
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define N 200
+#define MEAN 32.0
+#define STDEV 2.0
+#define ERROR_TOLERANCE 0.10
+
+int main()
+{
+    psStats * myStats = NULL;
+    int testStatus = true;
+    int globalTestStatus = true;
+    int i = 0;
+    psVector *myVector = NULL;
+    psVector *maskVector = NULL;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    int count = 0;
+    int currentId = psMemGetId();
+    int memLeaks = 0;
+    float realMeanNoMask = MEAN;
+    float realMedianNoMask = MEAN;
+    float realModeNoMask = MEAN;
+    float realStdevNoMask = STDEV * 0.33;
+    float realLQNoMask = MEAN - ( 0.6 * STDEV );
+    float realUQNoMask = MEAN + ( 0.6 * STDEV );
+    float realN50NoMask = ( float ) N / 4;
+    float realNfitNoMask = ( float ) N / 4;
+    float realMeanWithMask = MEAN;
+    float realMedianWithMask = MEAN;
+    float realModeWithMask = MEAN;
+    float realStdevWithMask = STDEV;
+    float realLQWithMask = MEAN;
+    float realUQWithMask = MEAN;
+    float realN50WithMask = ( float ) N / 4;
+    float realNfitWithMask = ( float ) N / 4;
+
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                              */
+    /*************************************************************************/
+    myStats = psStatsAlloc( PS_STAT_ROBUST_MEAN |
+                            PS_STAT_ROBUST_MEDIAN |
+                            PS_STAT_ROBUST_MODE |
+                            PS_STAT_ROBUST_STDEV |
+                            PS_STAT_ROBUST_QUARTILE );
+
+    maskVector = psVectorAlloc( N, PS_TYPE_U8 );
+    maskVector->n = N;
+    myVector = psGaussianDev( MEAN, STDEV, N );
+    // Set the mask vector and calculate the expected maximum.
+    for ( i = 0;i < N;i++ ) {
+        if ( i < ( N / 2 ) ) {
+            maskVector->data.U8[ i ] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[ i ] = 1;
+        }
+    }
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                            */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust mean: no vector mask" );
+
+    myStats = psVectorStats( myStats, myVector, NULL, 0 );
+
+    printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n",
+            realMeanNoMask, myStats->robustMean );
+
+    if ( fabs( myStats->robustMean - realMeanNoMask ) < ( ERROR_TOLERANCE * realMeanNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust mean: no vector mask",
+                 testStatus );
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Median: no vector mask" );
+
+    printf( "The expected Median was %.2f; the calculated Median was %.2f\n",
+            realMedianNoMask, myStats->robustMedian );
+    if ( fabs( myStats->robustMedian - realMedianNoMask ) < ( ERROR_TOLERANCE * realMedianNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Median: no vector mask",
+                 testStatus );
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Mode: no vector mask" );
+
+
+    printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
+            realModeNoMask, myStats->robustMode );
+    if ( fabs( myStats->robustMode - realModeNoMask ) < ( ERROR_TOLERANCE * realModeNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Mode: no vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Stdev: no vector mask" );
+
+    printf( "The expected Stdev was %.2f; the calculated Stdev was %.2f\n",
+            realStdevNoMask, myStats->robustStdev );
+    if ( fabs( myStats->robustStdev - realStdevNoMask ) < ( ERROR_TOLERANCE * realStdevNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Stdev: no vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: lower quartile: no vector mask" );
+
+    printf( "The expected LQ was %.2f; the calculated LQ was %.2f\n",
+            realLQNoMask, myStats->robustLQ );
+
+    if ( fabs( myStats->robustLQ - realLQNoMask ) < ( ERROR_TOLERANCE * realLQNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: upper quartile: no vector mask" );
+
+    printf( "The expected UQ was %.2f; the calculated UQ was %.2f\n",
+            realUQNoMask, myStats->robustUQ );
+    if ( fabs( myStats->robustUQ - realUQNoMask ) < ( ERROR_TOLERANCE * realUQNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust N50: no vector mask" );
+
+    // XXX:
+    realN50NoMask = myStats->robustN50;
+
+    printf( "The expected N50 was %.2f; the calculated N50 was %.2f\n",
+            realN50NoMask, myStats->robustN50 );
+    if ( fabs( myStats->robustN50 - realN50NoMask ) < ( ERROR_TOLERANCE * realN50NoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust N50: no vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Nfit: no vector mask" );
+
+    // XXX:
+    realNfitNoMask = myStats->robustNfit;
+
+    printf( "The expected Nfit was %.2f; the calculated Nfit was %.2f\n",
+            realNfitNoMask, myStats->robustNfit );
+    if ( fabs( myStats->robustNfit - realNfitNoMask ) < ( ERROR_TOLERANCE * realNfitNoMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Nfit: no vector mask",
+                 testStatus );
+
+
+    return ( 0 );
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                               */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust mean: with vector mask" );
+
+    printf( "Calling psVectorStats() on a vector with elements masked.\n" );
+    myStats = psVectorStats( myStats, myVector, maskVector, 1 );
+    printf( "Called psVectorStats() on a vector with elements masked.\n" );
+    printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n",
+            realMeanWithMask, myStats->robustMean );
+    if ( fabs( myStats->robustMean - realMeanWithMask ) < ( ERROR_TOLERANCE * realMeanWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust mean: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Median: with vector mask" );
+
+    printf( "The expected Median was %.2f; the calculated Median was %.2f\n",
+            realMedianWithMask, myStats->robustMedian );
+    if ( fabs( myStats->robustMedian - realMedianWithMask ) < ( ERROR_TOLERANCE * realMedianWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Median: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Mode: with vector mask" );
+
+    printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
+            realModeWithMask, myStats->robustMode );
+    if ( fabs( myStats->robustMode - realModeWithMask ) < ( ERROR_TOLERANCE * realModeWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Mode: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Stdev: with vector mask" );
+
+    printf( "The expected Stdev was %.2f; the calculated Stdev was %.2f\n",
+            realStdevWithMask, myStats->robustStdev );
+    if ( fabs( myStats->robustStdev - realStdevWithMask ) < ( ERROR_TOLERANCE * realStdevWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Stdev: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: lower quartile: with vector mask" );
+
+    printf( "The expected LQ was %.2f; the calculated LQ was %.2f\n",
+            realLQWithMask, myStats->robustLQ );
+    if ( fabs( myStats->robustLQ - realLQWithMask ) < ( ERROR_TOLERANCE * realLQWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: lower quartile: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: upper quartile: with vector mask" );
+
+    printf( "The expected UQ was %.2f; the calculated UQ was %.2f\n",
+            realUQWithMask, myStats->robustUQ );
+    if ( fabs( myStats->robustUQ - realUQWithMask ) < ( ERROR_TOLERANCE * realUQWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: lower quartile: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust N50: with vector mask" );
+
+    printf( "The expected N50 was %.2f; the calculated N50 was %.2f\n",
+            realN50WithMask, myStats->robustN50 );
+    if ( fabs( myStats->robustN50 - realN50WithMask ) < ( ERROR_TOLERANCE * realN50WithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust N50: with vector mask",
+                 testStatus );
+
+
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "PS_STAT_ROBUST_STATS: robust Nfit: with vector mask" );
+
+    printf( "The expected Nfit was %.2f; the calculated Nfit was %.2f\n",
+            realNfitWithMask, myStats->robustNfit );
+    if ( fabs( myStats->robustNfit - realNfitWithMask ) < ( ERROR_TOLERANCE * realNfitWithMask ) ) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter( stdout,
+                 "psVector functions",
+                 "PS_STAT_ROBUST_STATS: robust Nfit: with vector mask",
+                 testStatus );
+
+
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "psStats(): deallocating memory" );
+
+    psFree( myStats );
+    psFree( myVector );
+    psFree( maskVector );
+
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+    if ( 0 != memLeaks ) {
+        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+    }
+
+    printFooter( stdout,
+                 "psVector functions",
+                 "psStats(): deallocating memory",
+                 testStatus );
+
+    return ( !globalTestStatus );
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats08.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats08.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats08.c	(revision 1553)
@@ -0,0 +1,172 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_QUARTILE is correctly computed
+    by the procedure psArrayStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define N1 25  //
+#define N (8 * N1) // Don't change this (N must be a multiple of 8)
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    float realLQNoMask   = N/4.0;
+    float realUQNoMask   = 3.0 * (N/4.0);
+    float realLQWithMask   = N/8.0;
+    float realUQWithMask   = 3.0 * (N/8.0);
+    int count           = 0;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_QUARTILE);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_LQ: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected sampleLQ was %f; the calculated sampleLQ was %f\n",
+           realLQNoMask, myStats->sampleLQ);
+    if (fabs(realLQNoMask - myStats->sampleLQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_LQ: no vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_UQ: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected sampleUQ was %f; the calculated sampleUQ was %f\n",
+           realUQNoMask, myStats->sampleUQ);
+    if (fabs(realUQNoMask - myStats->sampleUQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_UQ: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_LQ: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The expected sampleLQ was %f; the calculated sampleLQ was %f\n",
+           realLQWithMask, myStats->sampleLQ);
+    if (fabs(realLQWithMask - myStats->sampleLQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_LQ: with vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_UQ: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, maskVector, 1);
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The expected sampleUQ was %f; the calculated sampleUQ was %f\n",
+           realUQWithMask, myStats->sampleUQ);
+    if (fabs(realUQWithMask - myStats->sampleUQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_UQ: with vector mask",
+                testStatus);
+
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psStats09.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psStats09.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psStats09.c	(revision 1553)
@@ -0,0 +1,146 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_CLIPPED_MEAN and
+    PS_STAT_CLIPPED_STDEV is calculate correctly by the procedure
+    psVectorStats().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "psImageStats.h"
+#include "float.h"
+#include <math.h>
+
+#define N 500
+#define MY_MEAN  30.0
+#define MY_RANGE 2.0
+
+int main()
+{
+    psStats *myStats    = NULL;
+    int testStatus      = true;
+    int globalTestStatus = true;
+    int i               = 0;
+    psVector *maskVector= NULL;
+    psVector *myGaussData  = NULL;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    //    float realclippedMeanNoMask  = 0.0;
+    //    float realclippedStdevNoMask = 0.0;
+    //    float realclippedMeanWithMask  = 0.0;
+    //    float realclippedStdevWithMask = 0.0;
+    int count           = 0;
+    int currentId       = psMemGetId();
+    int memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_CLIPPED_MEAN |
+                           PS_STAT_CLIPPED_STDEV);
+
+    myGaussData = psVectorAlloc(N, PS_TYPE_F32);
+    myGaussData->n = myGaussData->nalloc;
+    for (i=0;i<N;i++) {
+        myGaussData->data.F32[i] = MY_MEAN - (MY_RANGE/1.9) +
+                                   (MY_RANGE) * ((float) i) / ((float) N);
+    }
+
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_CLIPPED_MEAN: no vector mask");
+
+    myStats = psVectorStats(myStats, myGaussData, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The calculated clippedMean was %f\n", myStats->clippedMean);
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_CLIPPED_MEAN/STDEV: no vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_CLIPPED_STDEV: no vector mask");
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The calculated clippedStdev was %f\n", myStats->clippedStdev);
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_CLIPPED_MEAN/STDEV: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_CLIPPED_MEAN: vector mask");
+
+    myStats = psVectorStats(myStats, myGaussData, maskVector, 1);
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The calculated clippedMean was %f\n", myStats->clippedMean);
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_CLIPPED_MEAN/STDEV: vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_CLIPPED_STDEV: vector mask");
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The calculated clippedStdev was %f\n", myStats->clippedStdev);
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_CLIPPED_MEAN/STDEV: vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myGaussData);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /tags/rel2_1/psLib/test/dataManip/tst_psVectorFFT.c
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/tst_psVectorFFT.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/tst_psVectorFFT.c	(revision 1553)
@@ -0,0 +1,389 @@
+/** @file  tst_psVectorFFT.c
+*
+*  @brief Contains the tests for psFFT.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-06 22:34:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <math.h>
+#include <float.h>
+
+#include "psTest.h"
+#include "pslib.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (unsigned int row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (unsigned int col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static int testVectorFFT( void );
+static int testVectorRealImaginary( void );
+static int testVectorComplex( void );
+static int testVectorConjugate( void );
+static int testVectorPowerSpectrum( void );
+
+testDescription tests[] = {
+                              {
+                                  testVectorFFT, 600, "psVectorFFT", 0, false
+                              },
+                              {
+                                  testVectorRealImaginary, 601, "psVectorRealImaginary", 0, false
+                              },
+                              {
+                                  testVectorComplex, 602, "psVectorComplex", 0, false
+                              },
+                              {
+                                  testVectorConjugate, 603, "psVectorConjugate", 0, false
+                              },
+                              {
+                                  testVectorPowerSpectrum, 604, "psVectorPowerSpectrum", 0, false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main( int argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psFFT", tests, argc, argv ) );
+}
+
+int testVectorFFT( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+
+    /*
+    1. assign a vector to a sinisoid
+    2. perform a forward transform
+    3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    4. perform a reverse transform
+    5. compare to original (should be equal to within a reasonable error)
+    */
+
+    // 1. assign a vector to a sinisoid
+    vec = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec->n = vec->nalloc;
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        vec->data.F32[ n ] = sinf( ( psF32 ) n / 50.0f * M_PI );
+    }
+
+    // 2. perform a forward transform
+    vec2 = psVectorFFT( NULL, vec, PS_FFT_FORWARD );
+    if ( vec2->type.type != PS_TYPE_C32 ) {
+        psError( __func__, "FFT didn't produce complex values?" );
+        return 1;
+    }
+
+
+    // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        if ( n == 1 || n == 99 ) {
+            if ( fabsf( cabsf( vec2->data.C32[ n ] ) - 50.0f ) > 0.1f ) {
+                psError( __func__, "FFT didn't work for vector (n=%d)", n );
+                return 2;
+            }
+        } else {
+            if ( fabsf( cabsf( vec2->data.C32[ n ] ) ) > 0.1f ) {
+                psError( __func__, "FFT didn't work for vector (n=%d)", n );
+                return 3;
+            }
+        }
+    }
+
+    // 4. perform a reverse transform
+    vec3 = psVectorFFT( NULL, vec2, PS_FFT_REVERSE );
+    if ( vec3->type.type != PS_TYPE_C32 ) {
+        psError( __func__, "FFT didn't produce complex values?" );
+        return 4;
+    }
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        psF32 val = sinf( ( psF32 ) n / 50.0f * M_PI );
+        psF32 vecVal = crealf( vec3->data.C32[ n ] ) / 100;
+        if ( fabsf( vecVal - val ) > 0.1f ) {
+            psError( __func__, "Reverse FFT didn't give me the original vector back (n=%d) (%.2f vs %.2f)",
+                     n, vecVal, val );
+            return 5;
+        }
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+
+    return 0;
+}
+
+int testVectorRealImaginary( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+
+    /*
+    1. create a C32 complex vector with distinctly different real and imaginary parts.
+    2. call psVectorReal and psVectorImaginary
+    3. compare results to the real/imaginary components of input
+    */
+
+    // 1. create a C32 complex vector with distinctly different real and imaginary parts.
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec->n = vec->nalloc;
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * ( n * 2 );
+    }
+
+    // 2. call psVectorReal and psVectorImaginary
+    vec2 = psVectorReal( vec2, vec );
+    if ( vec2 == NULL ) {
+        psError( __func__, "psVectorReal returned a NULL?" );
+        return 1;
+    }
+    if ( vec2->type.type != PS_TYPE_F32 ) {
+        psError( __func__, "psVectorReal returned a wrong type (%d)?",
+                 vec2->type.type );
+        return 2;
+    }
+
+    vec3 = psVectorImaginary( vec3, vec );
+    if ( vec3 == NULL ) {
+        psError( __func__, "psVectorImaginary returned a NULL?" );
+        return 3;
+    }
+    if ( vec3->type.type != PS_TYPE_F32 ) {
+        psError( __func__, "psVectorImaginary returned a wrong type (%d)?",
+                 vec3->type.type );
+        return 4;
+    }
+
+    // 3. compare results to the real/imaginary components of input
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        psF32 r = n;
+        psF32 i = ( n * 2 );
+        if ( fabsf( vec2->data.F32[ n ] - r ) > FLT_EPSILON ) {
+            psError( __func__, "psVectorReal didn't return the real portion at n=%d",
+                     n );
+            return 5;
+        }
+        if ( fabsf( vec3->data.F32[ n ] - i ) > FLT_EPSILON ) {
+            psError( __func__, "psVectorImaginary didn't return the real portion at n=%d",
+                     n );
+            return 6;
+        }
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+
+    return 0;
+}
+
+int testVectorComplex( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+
+    /*
+    1. create two unique psF32 vectors of the same size
+    2. call psVectorComplex
+    3. verify that the result is a psC32
+    4. call psVectorReal and psVectorImaginary on step 2 results
+    5. compare step 4 results to input.
+
+    6. create a psF32 and a psF64 vector of the same size
+    7. call psVectorComplex
+    8. verify that an appropriate error occurred.
+
+    9. create two psf32 vectors of different sizes
+    10. call psVectorComplex
+    11. verify thet an appropriate error occurred.
+    */
+
+    // 1. create two unique psF32 vectors of the same size
+    vec = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec2 = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec->n = vec->nalloc;
+    vec2->n = vec2->nalloc;
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        vec->data.F32[ n ] = n;
+        vec2->data.F32[ n ] = ( n * 2 );
+    }
+
+    // 2. call psVectorComplex
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+
+    // 3. verify that the result is a psC32
+    if ( vec3->type.type != PS_TYPE_C32 ) {
+        psError( __func__, "Vector Type from psVectorComplex is not complex? (%d)",
+                 vec3->type.type );
+        return 1;
+    }
+
+    // 4. call psVectorReal and psVectorImaginary on step 2 results (not needed, just use crealf/cimagf)
+    // 5. compare step 4 results to input.
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        if ( fabsf( crealf( vec3->data.C32[ n ] ) - n ) > FLT_EPSILON ||
+                fabsf( cimagf( vec3->data.C32[ n ] ) - ( n * 2 ) ) > FLT_EPSILON ) {
+            psError( __func__, "psVectorComplex result is invalid (n=%d, %.2f+%.2fi)",
+                     n, crealf( vec3->data.C32[ n ] ), cimagf( vec3->data.C32[ n ] ) );
+            return 2;
+        };
+    }
+
+
+    // 6. create a psF32 and a psF64 vector of the same size
+    vec2 = psVectorRecycle( vec2, 100, PS_TYPE_F64 );
+
+    // 7. call psVectorComplex
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error (type mismatch)." );
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+    // 8. verify that an appropriate error occurred. (this partially has to be done via inspection)
+    if ( vec3 != NULL ) {
+        psError( __func__, "psVectorComplex returned a vector though input types mismatched." );
+        return 3;
+    }
+
+    // 9. create two psf32 vectors of different sizes
+    vec2 = psVectorRecycle( vec2, 200, PS_TYPE_F32 );
+
+    // 10. call psVectorComplex
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+
+    // 11. verify thet an appropriate error occurred. (actually, it isn't an error...)
+    if ( vec3->n != 100 ) {
+        psError( __func__, "psVectorComplex returned a larger vector than the input supported (%d).", vec3->n );
+        return 4;
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+
+    return 0;
+}
+
+int testVectorConjugate( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+
+    /*
+    1. create a psC32 with unique real and imaginary values.
+    2. call psVectorConjugate
+    3. verify result is psC32
+    4. verify each value is conjugate of input (a+bi -> a-bi)
+    */
+
+    // 1. create a psC32 with unique real and imaginary values.
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec->n = vec->nalloc;
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * ( n * 2 );
+    }
+
+    // 2. call psVectorConjugate
+    vec2 = psVectorConjugate( vec2, vec );
+
+    // 3. verify result is psC32
+    if ( vec2->type.type != PS_TYPE_C32 ) {
+        psError( __func__, "the psVectorConjugate didn't return a C32 vector" );
+        return 1;
+    }
+
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        if ( fabsf( crealf( vec->data.C32[ n ] ) - crealf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ||
+                fabsf( cimagf( vec->data.C32[ n ] ) + cimagf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ) {
+            psError( __func__, "psVectorComplex result is invalid (n=%d, %.2f+%.2fi)",
+                     n, crealf( vec2->data.C32[ n ] ), cimagf( vec2->data.C32[ n ] ) );
+            return 2;
+        };
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+
+    return 0;
+}
+
+int testVectorPowerSpectrum( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psF32 val;
+
+    /*
+    1. create a psC32 vector with unique real and imaginary components
+    2. call psVectorPowerSpectrum
+    3. verify result is psF32
+    4. verify the values are the square of the absolute values of the original
+    */
+
+    // 1. create a psC32 vector with unique real and imaginary components
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec->n = vec->nalloc;
+    for ( unsigned int n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * sinf( ( ( psF32 ) n ) / 50.f * M_PI );
+    }
+
+    // 2. call psVectorPowerSpectrum
+    vec2 = psVectorPowerSpectrum( vec2, vec );
+
+    // 3. verify result is psF32
+    if ( vec2->type.type != PS_TYPE_F32 ) {
+        psError( __func__, "the type was not PS_TYPE_F32." );
+        return 1;
+    }
+
+    // 4. verify the values are the square of the absolute values of the original
+    //   (ADD specifies something else)
+    //   P_0 = |C_0|^2/N^2
+    //   P_j = (|C_j|^2+|C_N-j|^2)/N^2
+    //   P_N/2 = |C_N/2|^2/N^2
+    //  where j = 1,2,...,(N/2-1)
+
+    val = cabsf( vec->data.C32[ 0 ] ) * cabsf( vec->data.C32[ 0 ] ) / 100 / 100;
+    if ( fabsf( vec2->data.F32[ 0 ] - val ) > FLT_EPSILON ) {
+        psError( __func__, "psVectorPowerSpectrum result is invalid (n=0, %.2f %.2f)",
+                 vec2->data.F32[ 0 ], val );
+        return 2;
+    };
+
+    for ( unsigned int n = 1; n < 50; n++ ) {
+        val = ( cabsf( vec->data.C32[ n ] ) * cabsf( vec->data.C32[ n ] ) +
+                cabsf( vec->data.C32[ 100 - n ] ) * cabsf( vec->data.C32[ 100 - n ] ) ) / 100 / 100;
+
+        if ( fabsf( val - vec2->data.F32[ n ] ) > FLT_EPSILON ) {
+            psError( __func__, "psVectorPowerSpectrum result is invalid (n=%d, %.2f %.2f)",
+                     n, vec2->data.F32[ n ], val );
+            return 2;
+        };
+    }
+
+    val = cabsf( vec->data.C32[ 50 ] ) * cabsf( vec->data.C32[ 50 ] ) / 100 / 100;
+    if ( fabsf( vec2->data.F32[ 50 ] - val ) > FLT_EPSILON ) {
+        psError( __func__, "psVectorPowerSpectrum result is invalid (n=50, %.2f %.2f)",
+                 vec2->data.F32[ 0 ], val );
+        return 2;
+    };
+
+    psFree( vec );
+    psFree( vec2 );
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc00.stdout	(revision 1553)
@@ -0,0 +1,80 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psPolynomial1D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x) = (5.000000): 2070.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psPolynomial1D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psPolynomial2D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x, y) = (5.000000, 5.000000): 322920.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psPolynomial2D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psPolynomial3D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x, y, z) = (5.000000, 5.000000, 5.000000): 1261325568.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psPolynomial3D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psPolynomial4D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (w, x, y, z) = (5.000000, 5.000000, 5.000000, 5.000000): 123176004616192.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psPolynomial4D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psDPolynomial1D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x) = (5.000000): 2070.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psDPolynomial1D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psDPolynomial2D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x, y) = (5.000000, 5.000000): 322920.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psDPolynomial2D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psDPolynomial3D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (x, y, z) = (5.000000, 5.000000, 5.000000): 1261325520.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psDPolynomial3D structure.} | tst_psFunc00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc00.c                                             *
+*            TestPoint: psFunctions functions{Allocate/Deallocate the psDPolynomial4D structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+At (w, x, y, z) = (5.000000, 5.000000, 5.000000, 5.000000): 123176004981120.000000
+
+---> TESTPOINT PASSED (psStats functions{Allocate/Deallocate the psDPolynomial4D structure.} | tst_psFunc00.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psFunc01.stdout	(revision 1553)
@@ -0,0 +1,108 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc01.c                                             *
+*            TestPoint: psFunctions functions{psGaussian()}                        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+normal psGaussian(0.000000) is 0.000000
+normal psGaussian(2.000000) is 0.000000
+normal psGaussian(4.000000) is 0.000000
+normal psGaussian(6.000000) is 0.000000
+normal psGaussian(8.000000) is 0.000000
+normal psGaussian(10.000000) is 0.000000
+normal psGaussian(12.000000) is 0.000000
+normal psGaussian(14.000000) is 0.000000
+normal psGaussian(16.000000) is 0.000000
+normal psGaussian(18.000000) is 0.000000
+normal psGaussian(20.000000) is 0.000001
+normal psGaussian(22.000000) is 0.000067
+normal psGaussian(24.000000) is 0.002216
+normal psGaussian(26.000000) is 0.026995
+normal psGaussian(28.000000) is 0.120985
+normal psGaussian(30.000000) is 0.199471
+normal psGaussian(32.000000) is 0.120985
+normal psGaussian(34.000000) is 0.026995
+normal psGaussian(36.000000) is 0.002216
+normal psGaussian(38.000000) is 0.000067
+normal psGaussian(40.000000) is 0.000001
+normal psGaussian(42.000000) is 0.000000
+normal psGaussian(44.000000) is 0.000000
+normal psGaussian(46.000000) is 0.000000
+normal psGaussian(48.000000) is 0.000000
+normal psGaussian(50.000000) is 0.000000
+normal psGaussian(52.000000) is 0.000000
+normal psGaussian(54.000000) is 0.000000
+normal psGaussian(56.000000) is 0.000000
+normal psGaussian(58.000000) is 0.000000
+NON-normal psGaussian(0.000000) is 0.000000
+NON-normal psGaussian(2.000000) is 0.000000
+NON-normal psGaussian(4.000000) is 0.000000
+NON-normal psGaussian(6.000000) is 0.000000
+NON-normal psGaussian(8.000000) is 0.000000
+NON-normal psGaussian(10.000000) is 0.000000
+NON-normal psGaussian(12.000000) is 0.000000
+NON-normal psGaussian(14.000000) is 0.000000
+NON-normal psGaussian(16.000000) is 0.000000
+NON-normal psGaussian(18.000000) is 0.000000
+NON-normal psGaussian(20.000000) is 0.000004
+NON-normal psGaussian(22.000000) is 0.000335
+NON-normal psGaussian(24.000000) is 0.011109
+NON-normal psGaussian(26.000000) is 0.135335
+NON-normal psGaussian(28.000000) is 0.606531
+NON-normal psGaussian(30.000000) is 1.000000
+NON-normal psGaussian(32.000000) is 0.606531
+NON-normal psGaussian(34.000000) is 0.135335
+NON-normal psGaussian(36.000000) is 0.011109
+NON-normal psGaussian(38.000000) is 0.000335
+NON-normal psGaussian(40.000000) is 0.000004
+NON-normal psGaussian(42.000000) is 0.000000
+NON-normal psGaussian(44.000000) is 0.000000
+NON-normal psGaussian(46.000000) is 0.000000
+NON-normal psGaussian(48.000000) is 0.000000
+NON-normal psGaussian(50.000000) is 0.000000
+NON-normal psGaussian(52.000000) is 0.000000
+NON-normal psGaussian(54.000000) is 0.000000
+NON-normal psGaussian(56.000000) is 0.000000
+NON-normal psGaussian(58.000000) is 0.000000
+
+---> TESTPOINT PASSED (psFunctions functions{psGaussian()} | tst_psFunc01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFunc01.c                                             *
+*            TestPoint: psFunctions functions{psGaussianDev()}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Gaussian Deviate [0] is 30.267838
+Gaussian Deviate [1] is 29.823797
+Gaussian Deviate [2] is 33.348816
+Gaussian Deviate [3] is 31.467281
+Gaussian Deviate [4] is 31.995049
+Gaussian Deviate [5] is 27.444996
+Gaussian Deviate [6] is 25.206570
+Gaussian Deviate [7] is 28.641439
+Gaussian Deviate [8] is 29.921818
+Gaussian Deviate [9] is 31.787111
+Gaussian Deviate [10] is 29.964705
+Gaussian Deviate [11] is 27.406887
+Gaussian Deviate [12] is 28.664040
+Gaussian Deviate [13] is 30.363417
+Gaussian Deviate [14] is 31.662102
+Gaussian Deviate [15] is 28.903503
+Gaussian Deviate [16] is 28.723936
+Gaussian Deviate [17] is 30.014177
+Gaussian Deviate [18] is 28.660292
+Gaussian Deviate [19] is 28.344475
+Gaussian Deviate [20] is 31.225000
+Gaussian Deviate [21] is 29.264824
+Gaussian Deviate [22] is 29.421013
+Gaussian Deviate [23] is 28.166250
+Gaussian Deviate [24] is 28.832390
+Gaussian Deviate [25] is 30.129230
+Gaussian Deviate [26] is 30.093487
+Gaussian Deviate [27] is 28.498547
+Gaussian Deviate [28] is 29.711535
+Gaussian Deviate [29] is 32.951122
+
+---> TESTPOINT PASSED (psFunctions functions{psGaussianDev()} | tst_psFunc01.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist00.stdout	(revision 1553)
@@ -0,0 +1,87 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 25.000)
+Bin number 1 bounds: (25.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 21.000)
+Bin number 1 bounds: (21.000 - 22.000)
+Bin number 2 bounds: (22.000 - 23.000)
+Bin number 3 bounds: (23.000 - 24.000)
+Bin number 4 bounds: (24.000 - 25.000)
+Bin number 5 bounds: (25.000 - 26.000)
+Bin number 6 bounds: (26.000 - 27.000)
+Bin number 7 bounds: (27.000 - 28.000)
+Bin number 8 bounds: (28.000 - 29.000)
+Bin number 9 bounds: (29.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 20.500)
+Bin number 1 bounds: (20.500 - 21.000)
+Bin number 2 bounds: (21.000 - 21.500)
+Bin number 3 bounds: (21.500 - 22.000)
+Bin number 4 bounds: (22.000 - 22.500)
+Bin number 5 bounds: (22.500 - 23.000)
+Bin number 6 bounds: (23.000 - 23.500)
+Bin number 7 bounds: (23.500 - 24.000)
+Bin number 8 bounds: (24.000 - 24.500)
+Bin number 9 bounds: (24.500 - 25.000)
+Bin number 10 bounds: (25.000 - 25.500)
+Bin number 11 bounds: (25.500 - 26.000)
+Bin number 12 bounds: (26.000 - 26.500)
+Bin number 13 bounds: (26.500 - 27.000)
+Bin number 14 bounds: (27.000 - 27.500)
+Bin number 15 bounds: (27.500 - 28.000)
+Bin number 16 bounds: (28.000 - 28.500)
+Bin number 17 bounds: (28.500 - 29.000)
+Bin number 18 bounds: (29.000 - 29.500)
+Bin number 19 bounds: (29.500 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure. (UPPER<LOWER)} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure. (UPPER<LOWER)} | tst_psHist00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist00.c                                             *
+*            TestPoint: psStats functions{Deallocate the psHistogram structure.}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Deallocate the psHistogram structure.} | tst_psHist00.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist01.stdout	(revision 1553)
@@ -0,0 +1,78 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist01.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist01.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 25.000)
+Bin number 1 bounds: (25.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist01.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 21.000)
+Bin number 1 bounds: (21.000 - 22.000)
+Bin number 2 bounds: (22.000 - 23.000)
+Bin number 3 bounds: (23.000 - 24.000)
+Bin number 4 bounds: (24.000 - 25.000)
+Bin number 5 bounds: (25.000 - 26.000)
+Bin number 6 bounds: (26.000 - 27.000)
+Bin number 7 bounds: (27.000 - 28.000)
+Bin number 8 bounds: (28.000 - 29.000)
+Bin number 9 bounds: (29.000 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist01.c                                             *
+*            TestPoint: psStats functions{Allocate the psHistogram structure.}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 20.500)
+Bin number 1 bounds: (20.500 - 21.000)
+Bin number 2 bounds: (21.000 - 21.500)
+Bin number 3 bounds: (21.500 - 22.000)
+Bin number 4 bounds: (22.000 - 22.500)
+Bin number 5 bounds: (22.500 - 23.000)
+Bin number 6 bounds: (23.000 - 23.500)
+Bin number 7 bounds: (23.500 - 24.000)
+Bin number 8 bounds: (24.000 - 24.500)
+Bin number 9 bounds: (24.500 - 25.000)
+Bin number 10 bounds: (25.000 - 25.500)
+Bin number 11 bounds: (25.500 - 26.000)
+Bin number 12 bounds: (26.000 - 26.500)
+Bin number 13 bounds: (26.500 - 27.000)
+Bin number 14 bounds: (27.000 - 27.500)
+Bin number 15 bounds: (27.500 - 28.000)
+Bin number 16 bounds: (28.000 - 28.500)
+Bin number 17 bounds: (28.500 - 29.000)
+Bin number 18 bounds: (29.000 - 29.500)
+Bin number 19 bounds: (29.500 - 30.000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psHistogram structure.} | tst_psHist01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist01.c                                             *
+*            TestPoint: psStats functions{Deallocate the psHistogram structure.}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Deallocate the psHistogram structure.} | tst_psHist01.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psHist02.stdout	(revision 1553)
@@ -0,0 +1,156 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.00 - 30.00) data (10000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram, no mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram with mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 30.000) data (5000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram with mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.00 - 25.00) data (5000)
+Bin number 1 bounds: (25.00 - 30.00) data (5000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram, no mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram with mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 25.000) data (5000)
+Bin number 1 bounds: (25.000 - 30.000) data (0)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram with mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.00 - 21.00) data (1000)
+Bin number 1 bounds: (21.00 - 22.00) data (1000)
+Bin number 2 bounds: (22.00 - 23.00) data (1000)
+Bin number 3 bounds: (23.00 - 24.00) data (1000)
+Bin number 4 bounds: (24.00 - 25.00) data (1000)
+Bin number 5 bounds: (25.00 - 26.00) data (1000)
+Bin number 6 bounds: (26.00 - 27.00) data (1000)
+Bin number 7 bounds: (27.00 - 28.00) data (1000)
+Bin number 8 bounds: (28.00 - 29.00) data (1000)
+Bin number 9 bounds: (29.00 - 30.00) data (1000)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram, no mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram with mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 21.000) data (1000)
+Bin number 1 bounds: (21.000 - 22.000) data (1000)
+Bin number 2 bounds: (22.000 - 23.000) data (1000)
+Bin number 3 bounds: (23.000 - 24.000) data (1000)
+Bin number 4 bounds: (24.000 - 25.000) data (1000)
+Bin number 5 bounds: (25.000 - 26.000) data (0)
+Bin number 6 bounds: (26.000 - 27.000) data (0)
+Bin number 7 bounds: (27.000 - 28.000) data (0)
+Bin number 8 bounds: (28.000 - 29.000) data (0)
+Bin number 9 bounds: (29.000 - 30.000) data (0)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram with mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.00 - 20.50) data (500)
+Bin number 1 bounds: (20.50 - 21.00) data (500)
+Bin number 2 bounds: (21.00 - 21.50) data (500)
+Bin number 3 bounds: (21.50 - 22.00) data (500)
+Bin number 4 bounds: (22.00 - 22.50) data (500)
+Bin number 5 bounds: (22.50 - 23.00) data (500)
+Bin number 6 bounds: (23.00 - 23.50) data (500)
+Bin number 7 bounds: (23.50 - 24.00) data (500)
+Bin number 8 bounds: (24.00 - 24.50) data (500)
+Bin number 9 bounds: (24.50 - 25.00) data (500)
+Bin number 10 bounds: (25.00 - 25.50) data (500)
+Bin number 11 bounds: (25.50 - 26.00) data (500)
+Bin number 12 bounds: (26.00 - 26.50) data (500)
+Bin number 13 bounds: (26.50 - 27.00) data (500)
+Bin number 14 bounds: (27.00 - 27.50) data (500)
+Bin number 15 bounds: (27.50 - 28.00) data (500)
+Bin number 16 bounds: (28.00 - 28.50) data (500)
+Bin number 17 bounds: (28.50 - 29.00) data (500)
+Bin number 18 bounds: (29.00 - 29.50) data (500)
+Bin number 19 bounds: (29.50 - 30.00) data (500)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram, no mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Allocate and Perform Histogram with mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (20.000 - 20.500) data (500)
+Bin number 1 bounds: (20.500 - 21.000) data (500)
+Bin number 2 bounds: (21.000 - 21.500) data (500)
+Bin number 3 bounds: (21.500 - 22.000) data (500)
+Bin number 4 bounds: (22.000 - 22.500) data (500)
+Bin number 5 bounds: (22.500 - 23.000) data (500)
+Bin number 6 bounds: (23.000 - 23.500) data (500)
+Bin number 7 bounds: (23.500 - 24.000) data (500)
+Bin number 8 bounds: (24.000 - 24.500) data (500)
+Bin number 9 bounds: (24.500 - 25.000) data (500)
+Bin number 10 bounds: (25.000 - 25.500) data (0)
+Bin number 11 bounds: (25.500 - 26.000) data (0)
+Bin number 12 bounds: (26.000 - 26.500) data (0)
+Bin number 13 bounds: (26.500 - 27.000) data (0)
+Bin number 14 bounds: (27.000 - 27.500) data (0)
+Bin number 15 bounds: (27.500 - 28.000) data (0)
+Bin number 16 bounds: (28.000 - 28.500) data (0)
+Bin number 17 bounds: (28.500 - 29.000) data (0)
+Bin number 18 bounds: (29.000 - 29.500) data (0)
+Bin number 19 bounds: (29.500 - 30.000) data (0)
+
+---> TESTPOINT PASSED (psStats functions{Allocate and Perform Histogram with mask} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Calling psVectorHistogram() with various NULL inputs.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Calling psVectorHistogram() with various NULL inputs.} | tst_psHist02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHist02.c                                             *
+*            TestPoint: psStats functions{Deallocate the psHistogram structure.}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Deallocate the psHistogram structure.} | tst_psHist02.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix01.stdout	(revision 1553)
@@ -0,0 +1,45 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix01.c                                           *
+*            TestPoint: psMatrix{Create input and output images}                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+7.000000 8.000000 9.000000 
+4.000000 5.000000 6.000000 
+1.000000 2.000000 3.000000 
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images} | tst_psMatrix01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix01.c                                           *
+*            TestPoint: psMatrix{Transpose input image into output image}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+3.000000 6.000000 9.000000 
+2.000000 5.000000 8.000000 
+1.000000 4.000000 7.000000 
+
+---> TESTPOINT PASSED (psMatrix{Transpose input image into output image} | tst_psMatrix01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix01.c                                           *
+*            TestPoint: psMatrix{ranspose input image into auto allocated NULL output image} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+3.000000 6.000000 9.000000 
+2.000000 5.000000 8.000000 
+1.000000 4.000000 7.000000 
+
+---> TESTPOINT PASSED (psMatrix{ranspose input image into auto allocated NULL output image} | tst_psMatrix01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix01.c                                           *
+*            TestPoint: psMatrix{Free images and check for leaks}                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free images and check for leaks} | tst_psMatrix01.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stderr	(revision 1553)
@@ -0,0 +1,6 @@
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: Pointer to inImage is same as outImage.
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: inImage or its data is NULL.
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: inImage not PS_TYPE_F64.
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: inImage not square array.
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: outImage not PS_TYPE_F64.
+<DATE><TIME>|<HOST>|E|psMatrixTranspo|Invalid operation: outImage not square array.
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix02.stdout	(revision 1553)
@@ -0,0 +1,66 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Input pointer same as output pointer}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: Pointer to inImage is same as outImage. *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Input pointer same as output pointer} | tst_psMatrix02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Null input psImage}                               *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage or its data is NULL.            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Null input psImage} | tst_psMatrix02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Incorrect type for input pointer}                 *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: |Invalid operation: inImage not PS_TYPE_F64.               *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Incorrect type for input pointer} | tst_psMatrix02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Matrix not square for input pointer}              *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage not square array.               *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Matrix not square for input pointer} | tst_psMatrix02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Incorrect type for output pointer}                *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: outImage not PS_TYPE_F64.               *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Incorrect type for output pointer} | tst_psMatrix02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix02.c                                           *
+*            TestPoint: psMatrix{Matrix not square for output pointer}             *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: outImage not square array.              *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Matrix not square for output pointer} | tst_psMatrix02.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stderr	(revision 1553)
@@ -0,0 +1,3 @@
+<DATE><TIME>|<HOST>|E|    psMatrixLUD|Invalid operation: inImage or its data is NULL.
+<DATE><TIME>|<HOST>|E|psMatrixLUSolve|Invalid operation: inVector or its data is NULL.
+<DATE><TIME>|<HOST>|E|psMatrixLUSolve|Invalid operation: inImage or its data is NULL.
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix03.stdout	(revision 1553)
@@ -0,0 +1,82 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Create input and output images and vectors}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+3.000000 1.000000 -2.000000 
+4.000000 5.000000 6.000000 
+2.000000 4.000000 6.000000 
+
+18.000000
+24.000000
+4.000000
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images and vectors} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Calculate LU matrix}                              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.500000 -0.545455 -0.545455 
+0.750000 -2.750000 -6.500000 
+4.000000 5.000000 6.000000 
+
+---> TESTPOINT PASSED (psMatrix{Calculate LU matrix} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Determine solution to matrix equation}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+4.000000
+-2.000000
+3.000000
+
+---> TESTPOINT PASSED (psMatrix{Determine solution to matrix equation} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Free input and output images and vectors}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free input and output images and vectors} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Attempt to use null image input argument}         *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage or its data is NULL.            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null image input argument} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Attempt to use null input vector argument}        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inVector or its data is NULL.           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null input vector argument} | tst_psMatrix03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix03.c                                           *
+*            TestPoint: psMatrix{Attempt to use null LU image argument}            *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage or its data is NULL.            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null LU image argument} | tst_psMatrix03.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stderr	(revision 1553)
@@ -0,0 +1,2 @@
+<DATE><TIME>|<HOST>|E| psMatrixInvert|Invalid operation: inImage or its data is NULL.
+<DATE><TIME>|<HOST>|E| psMatrixInvert|Invalid operation: determinant argument is NULL.
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix04.stdout	(revision 1553)
@@ -0,0 +1,67 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Create input and output images}                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+3.000000 5.000000 7.000000 
+0.000000 1.000000 -1.000000 
+2.000000 4.000000 3.000000 
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images} | tst_psMatrix04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Invert matrix and calculate determinant}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+-1.000000 0.666667 0.666667 
+-1.000000 1.666667 0.666667 
+4.000000 -4.333333 -2.333333 
+
+det = 3.000000
+
+---> TESTPOINT PASSED (psMatrix{Invert matrix and calculate determinant} | tst_psMatrix04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Calculate determinant only}                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+det = 3.000000
+
+---> TESTPOINT PASSED (psMatrix{Calculate determinant only} | tst_psMatrix04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Free input and output images}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free input and output images} | tst_psMatrix04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Attempt to use null input image argument}         *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage or its data is NULL.            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null input image argument} | tst_psMatrix04.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix04.c                                           *
+*            TestPoint: psMatrix{Attempt to use null input float argument}         *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: determinant argument is NULL.           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null input float argument} | tst_psMatrix04.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix05.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix05.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix05.stdout	(revision 1553)
@@ -0,0 +1,34 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix05.c                                           *
+*            TestPoint: psMatrix{Create input and output images}                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+2.000000 3.000000 
+-1.000000 2.000000 
+
+4.000000 1.000000 
+0.000000 6.000000 
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images} | tst_psMatrix05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix05.c                                           *
+*            TestPoint: psMatrix{Multiply images}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+8.000000 20.000000 
+-4.000000 11.000000 
+
+---> TESTPOINT PASSED (psMatrix{Multiply images} | tst_psMatrix05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix05.c                                           *
+*            TestPoint: psMatrix{Free input and output images}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free input and output images} | tst_psMatrix05.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix06.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix06.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix06.stdout	(revision 1553)
@@ -0,0 +1,35 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix06.c                                           *
+*            TestPoint: psMatrix{Create input and output images}                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+1.000000 0.500000 0.333333 0.250000 
+0.500000 0.333333 0.250000 0.200000 
+0.333333 0.250000 0.200000 0.166667 
+0.250000 0.200000 0.166667 0.142857 
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images} | tst_psMatrix06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix06.c                                           *
+*            TestPoint: psMatrix{Calculate Eigenvectors}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.792608 0.582076 -0.179186 -0.029193 
+0.451923 -0.370502 0.741918 0.328712 
+0.322416 -0.509579 -0.100228 -0.791411 
+0.252161 -0.514048 -0.638283 0.514553 
+
+---> TESTPOINT PASSED (psMatrix{Calculate Eigenvectors} | tst_psMatrix06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix06.c                                           *
+*            TestPoint: psMatrix{Free input and output images}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free input and output images} | tst_psMatrix06.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stderr	(revision 1553)
@@ -0,0 +1,3 @@
+<DATE><TIME>|<HOST>|E|psMatrixToVecto|Invalid operation: inImage or its data is NULL.
+<DATE><TIME>|<HOST>|E|psMatrixToVecto|Image does not have dim with 1 col or 1 row: (2 x 2).
+<DATE><TIME>|<HOST>|E|psVectorToMatri|Invalid operation: inVector or its data is NULL.
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrix07.stdout	(revision 1553)
@@ -0,0 +1,106 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Create input and output images and vectors}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.000000 
+1.000000 
+2.000000 
+
+0.000000 1.000000 2.000000 
+
+0.000000
+1.000000
+2.000000
+
+---> TESTPOINT PASSED (psMatrix{Create input and output images and vectors} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Convert matrix to PS_DIMEN_VECTOR vector}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.000000
+1.000000
+2.000000
+
+---> TESTPOINT PASSED (psMatrix{Convert matrix to PS_DIMEN_VECTOR vector} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Attempt to use null image input argument}         *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inImage or its data is NULL.            *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null image input argument} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Convert matrix to PS_DIMEN_TRANSV vector}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.000000
+1.000000
+2.000000
+
+---> TESTPOINT PASSED (psMatrix{Convert matrix to PS_DIMEN_TRANSV vector} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Improper image size}                              *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Image does not have dim with 1 col or 1 row: (2 x 2).      *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Improper image size} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Convert PS_DIMEN_VECTOR vector to matrix}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.000000 
+1.000000 
+2.000000 
+
+---> TESTPOINT PASSED (psMatrix{Convert PS_DIMEN_VECTOR vector to matrix} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Attempt to use null input vector argument}        *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation: inVector or its data is NULL.           *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Attempt to use null input vector argument} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Convert PS_DIMEN_TRANSV vector to matrix}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+0.000000 1.000000 2.000000 
+
+---> TESTPOINT PASSED (psMatrix{Convert PS_DIMEN_TRANSV vector to matrix} | tst_psMatrix07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrix07.c                                           *
+*            TestPoint: psMatrix{Free input and output images and vectors}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psMatrix{Free input and output images and vectors} | tst_psMatrix07.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic01.stdout	(revision 1553)
@@ -0,0 +1,1156 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10 10 
+10 10 
+10 10 
+
+10 10 
+10 10 
+10 10 
+
+Output:
+20 20 
+20 20 
+20 20 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+Output:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20 20 
+20 20 
+20 20 
+
+10 10 
+10 10 
+10 10 
+
+Output:
+10 10 
+10 10 
+10 10 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+Output:
+0.000000+400.000000i 0.000000+400.000000i 
+0.000000+400.000000i 0.000000+400.000000i 
+0.000000+400.000000i 0.000000+400.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20 20 
+20 20 
+20 20 
+
+10 10 
+10 10 
+10 10 
+
+Output:
+200 200 
+200 200 
+200 200 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+200.000000 200.000000 
+200.000000 200.000000 
+200.000000 200.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+200.000000 200.000000 
+200.000000 200.000000 
+200.000000 200.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+Output:
+0.000000+400.000000i 0.000000+400.000000i 
+0.000000+400.000000i 0.000000+400.000000i 
+0.000000+400.000000i 0.000000+400.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+Output:
+2.000000+0.000000i 2.000000+0.000000i 
+2.000000+0.000000i 2.000000+0.000000i 
+2.000000+0.000000i 2.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20 20 
+20 20 
+20 20 
+
+10 10 
+10 10 
+10 10 
+
+Output:
+2 2 
+2 2 
+2 2 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+2.000000 2.000000 
+2.000000 2.000000 
+2.000000 2.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+Output:
+2.000000 2.000000 
+2.000000 2.000000 
+2.000000 2.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+Output:
+2.000000+0.000000i 2.000000+0.000000i 
+2.000000+0.000000i 2.000000+0.000000i 
+2.000000+0.000000i 2.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-matrix psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10 10 
+10 10 
+10 10 
+
+5 5 5 
+
+Output:
+15 15 
+15 15 
+15 15 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+5.000000+5.000000i 5.000000+5.000000i 5.000000+5.000000i 
+
+Output:
+15.000000+15.000000i 15.000000+15.000000i 
+15.000000+15.000000i 15.000000+15.000000i 
+15.000000+15.000000i 15.000000+15.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20 20 
+20 20 
+20 20 
+
+5 5 5 
+
+Output:
+15 15 
+15 15 
+15 15 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 5.000000+5.000000i 5.000000+5.000000i 
+
+Output:
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20 20 
+20 20 
+20 20 
+
+5 5 5 
+
+Output:
+100 100 
+100 100 
+100 100 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+100.000000 100.000000 
+100.000000 100.000000 
+100.000000 100.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+100.000000 100.000000 
+100.000000 100.000000 
+100.000000 100.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 5.000000+5.000000i 5.000000+5.000000i 
+
+Output:
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 5.000000+5.000000i 5.000000+5.000000i 
+
+Output:
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20 20 
+20 20 
+20 20 
+
+5 5 5 
+
+Output:
+4 4 
+4 4 
+4 4 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+4.000000 4.000000 
+4.000000 4.000000 
+4.000000 4.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 5.000000 5.000000 
+
+Output:
+4.000000 4.000000 
+4.000000 4.000000 
+4.000000 4.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-vector psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 5.000000+5.000000i 5.000000+5.000000i 
+
+Output:
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-vector psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10 10 
+10 10 
+10 10 
+
+5 
+
+Output:
+15 15 
+15 15 
+15 15 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000 10.000000 
+10.000000 10.000000 
+10.000000 10.000000 
+
+5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: +
+Input:
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+10.000000+10.000000i 10.000000+10.000000i 
+
+5.000000+5.000000i 
+
+Output:
+15.000000+15.000000i 15.000000+15.000000i 
+15.000000+15.000000i 15.000000+15.000000i 
+15.000000+15.000000i 15.000000+15.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20 20 
+20 20 
+20 20 
+
+5 
+
+Output:
+15 15 
+15 15 
+15 15 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: -
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+15.000000 15.000000 
+15.000000 15.000000 
+15.000000 15.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 
+
+Output:
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20 20 
+20 20 
+20 20 
+
+5 
+
+Output:
+100 100 
+100 100 
+100 100 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+100.000000 100.000000 
+100.000000 100.000000 
+100.000000 100.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+100.000000 100.000000 
+100.000000 100.000000 
+100.000000 100.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: *
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 
+
+Output:
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+0.000000+200.000000i 0.000000+200.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 
+
+Output:
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20 20 
+20 20 
+20 20 
+
+5 
+
+Output:
+4 4 
+4 4 
+4 4 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+4.000000 4.000000 
+4.000000 4.000000 
+4.000000 4.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000 20.000000 
+20.000000 20.000000 
+20.000000 20.000000 
+
+5.000000 
+
+Output:
+4.000000 4.000000 
+4.000000 4.000000 
+4.000000 4.000000 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic01.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: /
+Input:
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+20.000000+20.000000i 20.000000+20.000000i 
+
+5.000000+5.000000i 
+
+Output:
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+4.000000+0.000000i 4.000000+0.000000i 
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix-scalar psBinaryOp} | tst_psMatrixVectorArithmetic01.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic02.stdout	(revision 1553)
@@ -0,0 +1,1700 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test matrix psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test matrix psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: abs
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: exp
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ln
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: ten
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: log
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: sin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dsin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: cos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dcos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: tan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dtan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: asin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dasin
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: acos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: dacos
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: atan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic02.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Test vector psUnaryOp}            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Operation: datan
+
+
+---> TESTPOINT PASSED (psMatrixVectorArithmetic{Test vector psUnaryOp} | tst_psMatrixVectorArithmetic02.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stderr	(revision 1553)
@@ -0,0 +1,27 @@
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Line <LINENO> - Null out argument
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Line <LINENO> - Null in1 argument
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Line <LINENO> - Null in2 argument
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Line <LINENO> - Null op argument
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Line <LINENO> - Null out argument
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Line <LINENO> - Null in argument
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Line <LINENO> - Null op argument
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Line <LINENO> - Element types for arguments inconsistent: (1028, 1032, 1032)
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Line <LINENO> - Element types for arguments inconsistent: (1028, 1032)
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Inconsistent element count: numRows: 2 vs 3 numCols: 2 vs 3
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Inconsistent element count: numRows: 2 vs 3 numCols: 2 vs 3
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Inconsistent element count: 2 vs 3
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Inconsistent element count: 2 vs 3
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Line <LINENO> - Dimensionality for arguments inconsistent: (1, 3)
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|       psNanDiv|: Divide by zero
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Minimum operation not supported for complex numbers
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Maximum operation not supported for complex numbers
+<DATE><TIME>|<HOST>|E|     psBinaryOp|: Invalid operation: yarg
+<DATE><TIME>|<HOST>|E|      psUnaryOp|: Invalid operation: yarg
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psMatrixVectorArithmetic03.stdout	(revision 1553)
@@ -0,0 +1,88 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Check for NULL arguments}         *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Null XXX argument                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Check for NULL arguments} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Inconsistent element types}       *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Element types for arguments inconsistent                   *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Inconsistent element types} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Inconsistent element count}       *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Inconsistent element count                                 *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Inconsistent element count} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Inconsistent dimensionality}      *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Dimensionality for arguments inconsistent                  *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Inconsistent dimensionality} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Divide by zero}                   *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Divide by zero                                             *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Division by zero} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Use min with complex numbers}     *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Minimum operation not supported for complex numbers        *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Use min with complex numbers} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Use max with complex numbers}     *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Maximum operation not supported for complex numbers        *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Use max with complex numbers} | tst_psMatrixVectorArithmetic03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMatrixVectorArithmetic03.c                           *
+*            TestPoint: psMatrixVectorArithmetic{Invalid operation}                *
+*             TestType: Negative                                                   *
+*    ExpectedErrorText: Invalid operation                                          *
+*  ExpectedStatusValue: 0                                                          *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psBitSet{Invalid operation} | tst_psMatrixVectorArithmetic03.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats00.stdout	(revision 1553)
@@ -0,0 +1,62 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEAN: no vector mask}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected mean was 4.500000; the calculated mean was 4.500000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_MEAN: no vector mask} | tst_psStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEAN: with vector mask=1} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected mean was 2.000000; the calculated mean was 2.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_MEAN: with vector mask=1} | tst_psStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEAN: with vector mask=2} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected mean was 2.000000; the calculated mean was 2.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_MEAN: with vector mask=2} | tst_psStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEAN: with vector mask=3} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected mean was 2.000000; the calculated mean was 2.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_MEAN: with vector mask=3} | tst_psStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEAN: NULL inputs}        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_MEAN: NULL inputs} | tst_psStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats00.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats00.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats01.stdout	(revision 1553)
@@ -0,0 +1,36 @@
+Masking element 5
+Masking element 6
+Masking element 7
+Masking element 8
+Masking element 9
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats01.c                                            *
+*            TestPoint: psStats functions{PS_STAT_MAX: no vector mask}             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected max was 9.000000; the calculated max was 9.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_MAX: no vector mask} | tst_psStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats01.c                                            *
+*            TestPoint: psStats functions{PS_STAT_MAX: with vector mask}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected max was 4.000000; the calculated max was 4.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_MAX: with vector mask} | tst_psStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats01.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats01.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats02.stdout	(revision 1553)
@@ -0,0 +1,31 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats02.c                                            *
+*            TestPoint: psStats functions{PS_STAT_MIN: no vector mask}             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected min was 0.000000; the calculated min was 0.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_MIN: no vector mask} | tst_psStats02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats02.c                                            *
+*            TestPoint: psStats functions{PS_STAT_MIN: with vector mask}           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected min was 5.000000; the calculated min was 5.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_MIN: with vector mask} | tst_psStats02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats02.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats02.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats03.stdout	(revision 1553)
@@ -0,0 +1,31 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats03.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEDIAN: no vector mask}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected median was 2058.000000.  The calculated median was 2058.000000.
+
+---> TESTPOINT PASSED (psStats functions{PS_STAT_SAMPLE_MEDIAN: no vector mask} | tst_psStats03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats03.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_MEDIAN: with vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected median was 1028.500000.  The calculated median was 1028.500000.
+
+---> TESTPOINT PASSED (psStats functions{PS_STAT_SAMPLE_MEDIAN: with vector mask} | tst_psStats03.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats03.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{psStats(): deallocating memory} | tst_psStats03.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats05.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats05.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats05.stdout	(revision 1553)
@@ -0,0 +1,18 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats05.c                                            *
+*            TestPoint: psStats functions{Allocate the psStats structure.}         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Allocate the psStats structure.} | tst_psStats05.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats05.c                                            *
+*            TestPoint: psStats functions{Deallocate the psStats structure.}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStats functions{Deallocate the psStats structure.} | tst_psStats05.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats06.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats06.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats06.stdout	(revision 1553)
@@ -0,0 +1,31 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats06.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_STDEV: no vector mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected stdev was 4.472136; the calculated stdev was 4.472136
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_STDEV: no vector mask} | tst_psStats06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats06.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_STDEV: with vector mask}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with last N/2 elements masked.
+The expected stdev was 2.160247; the calculated stdev was 2.160247
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_STDEV: with vector mask} | tst_psStats06.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats06.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats06.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats07.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats07.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats07.stdout	(revision 1553)
@@ -0,0 +1,81 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust mean: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+(LQBinNum, UQBinNum, maxBinNum) is (15, 35, 27)
+The expected Mean was 32.00; the calculated Mean was 32.59
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust mean: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust Median: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected Median was 32.00; the calculated Median was 32.49
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust Median: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust Mode: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected Mode was 32.00; the calculated Mode was 32.59
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust Mode: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust Stdev: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected Stdev was 0.66; the calculated Stdev was 0.66
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust Stdev: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: lower quartile: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected LQ was 30.80; the calculated LQ was 30.02
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: lower quartile: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: upper quartile: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected UQ was 33.20; the calculated UQ was 34.33
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: lower quartile: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust N50: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected N50 was 143.00; the calculated N50 was 143.00
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust N50: no vector mask} | tst_psStats07.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats07.c                                            *
+*            TestPoint: psStats functions{PS_STAT_ROBUST_STATS: robust Nfit: no vector mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The expected Nfit was 80.00; the calculated Nfit was 80.00
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_ROBUST_STATS: robust Nfit: no vector mask} | tst_psStats07.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats08.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats08.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats08.stdout	(revision 1553)
@@ -0,0 +1,53 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats08.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_LQ: no vector mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected sampleLQ was 50.000000; the calculated sampleLQ was 50.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_LQ: no vector mask} | tst_psStats08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats08.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_UQ: no vector mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The expected sampleUQ was 150.000000; the calculated sampleUQ was 150.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_UQ: no vector mask} | tst_psStats08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats08.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_LQ: with vector mask}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with elements masked.
+The expected sampleLQ was 25.000000; the calculated sampleLQ was 25.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_LQ: with vector mask} | tst_psStats08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats08.c                                            *
+*            TestPoint: psStats functions{PS_STAT_SAMPLE_UQ: with vector mask}     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with elements masked.
+The expected sampleUQ was 75.000000; the calculated sampleUQ was 75.000000
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_SAMPLE_UQ: with vector mask} | tst_psStats08.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats08.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats08.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats09.stdout
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats09.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psStats09.stdout	(revision 1553)
@@ -0,0 +1,53 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats09.c                                            *
+*            TestPoint: psStats functions{PS_STAT_CLIPPED_MEAN: no vector mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The calculated clippedMean was 29.945370
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_CLIPPED_MEAN/STDEV: no vector mask} | tst_psStats09.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats09.c                                            *
+*            TestPoint: psStats functions{PS_STAT_CLIPPED_STDEV: no vector mask}   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with no elements masked.
+The calculated clippedStdev was 0.577927
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_CLIPPED_MEAN/STDEV: no vector mask} | tst_psStats09.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats09.c                                            *
+*            TestPoint: psStats functions{PS_STAT_CLIPPED_MEAN: vector mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with elements masked.
+The calculated clippedMean was 29.945370
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_CLIPPED_MEAN/STDEV: vector mask} | tst_psStats09.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats09.c                                            *
+*            TestPoint: psStats functions{PS_STAT_CLIPPED_STDEV: vector mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Called psVectorStats() on a vector with elements masked.
+The calculated clippedStdev was 0.285787
+
+---> TESTPOINT PASSED (psVector functions{PS_STAT_CLIPPED_MEAN/STDEV: vector mask} | tst_psStats09.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStats09.c                                            *
+*            TestPoint: psStats functions{psStats(): deallocating memory}          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psVector functions{psStats(): deallocating memory} | tst_psStats09.c)
+
Index: /tags/rel2_1/psLib/test/dataManip/verified/tst_psVectorFFT.stderr
===================================================================
--- /tags/rel2_1/psLib/test/dataManip/verified/tst_psVectorFFT.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/dataManip/verified/tst_psVectorFFT.stderr	(revision 1553)
@@ -0,0 +1,47 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorFFT.c                                          *
+*            TestPoint: psFFT{psVectorFFT}                                         *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psVectorFFT} | tst_psVectorFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorFFT.c                                          *
+*            TestPoint: psFFT{psVectorRealImaginary}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psVectorRealImaginary} | tst_psVectorFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorFFT.c                                          *
+*            TestPoint: psFFT{psVectorComplex}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testVectorCompl|Following should be an error (type mismatch).
+<DATE><TIME>|<HOST>|E|psVectorComplex|The inputs to psVectorComplex must be the same type.
+
+---> TESTPOINT PASSED (psFFT{psVectorComplex} | tst_psVectorFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorFFT.c                                          *
+*            TestPoint: psFFT{psVectorConjugate}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psVectorConjugate} | tst_psVectorFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psVectorFFT.c                                          *
+*            TestPoint: psFFT{psVectorPowerSpectrum}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psVectorPowerSpectrum} | tst_psVectorFFT.c)
+
Index: /tags/rel2_1/psLib/test/image/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/image/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/.cvsignore	(revision 1553)
@@ -0,0 +1,9 @@
+temp
+tst_psImage
+tst_psImageExtraction
+tst_psImageFFT
+tst_psImageManip
+tst_psImageStats00
+tst_psImageStats01
+tst_psImageStats02
+tst_psImageStats03
Index: /tags/rel2_1/psLib/test/image/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/image/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/Makefile	(revision 1553)
@@ -0,0 +1,51 @@
+################################################################################
+##
+##  Makefile:   test/collections
+##
+##  $Revision: 1.2.2.1 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-16 23:59:01 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+include ../../src/Makefile.Globals
+
+CFLAGS := -I../../include $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+
+TARGET = tst_psImage \
+tst_psImageFFT \
+tst_psImageManip \
+tst_psImageStats00 \
+tst_psImageStats01 \
+tst_psImageStats02 \
+tst_psImageStats03 \
+tst_psImageExtraction
+
+OBJS = $(addsuffix .o,$(TARGET))
+
+all: $(TARGET)
+
+clean:
+	@echo "    Deleting executable and binary files for 'test/collections'"
+	$(RM) $(OBJS)
+
+distclean: clean
+	$(RM) $(TARGET)
+
+install: $(testbindir) $(testbindir)/verified $(TARGET)
+	install $(TARGET) $(testbindir)
+	install verified/*.stderr verified/*.stdout verified/*.fits $(testbindir)/verified
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
+$(testbindir)/verified:
+	mkdir -p $(testbindir)/verified
+
+
Index: /tags/rel2_1/psLib/test/image/tst_psImage.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImage.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImage.c	(revision 1553)
@@ -0,0 +1,634 @@
+/** @file  tst_psImage.c
+ *
+ *  @brief Contains the tests for psImage.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "psTest.h"
+#include "pslib.h"
+#include "psType.h"
+
+static int testImageAlloc(void);
+static int testImageSubset(void);
+static int testImageCopy(void);
+
+testDescription tests[] = {
+                              {
+                                  testImageAlloc,546,"psImageAlloc",0,false
+                              },
+                              {
+                                  testImageAlloc,548,"psImageFree",0,true
+                              },
+                              {
+                                  testImageSubset,547,"psImageSubset",0,false
+                              },
+                              {
+                                  testImageSubset,550,"psImageSubset",0,true
+                              },
+                              {
+                                  testImageCopy,551,"psImageCopy",0,false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if (! runTestSuite(stderr,"psImage",tests,argc,argv)) {
+        psError(__FILE__,"One or more tests failed");
+        return 1;
+    }
+    return 0;
+}
+
+int testImageAlloc(void)
+{
+    psImage* image = NULL;
+    unsigned int sizes = 6;
+    unsigned int numCols[] = {
+                                 0,1,1,100,100,150
+                             };
+    unsigned int numRows[] = {
+                                 0,1,100,1,150,100
+                             };
+    unsigned int types = 12;
+    psElemType type[] = { PS_TYPE_S8, PS_TYPE_S16, PS_TYPE_S32, PS_TYPE_S64,
+                          PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_U32, PS_TYPE_U64,
+                          PS_TYPE_F32, PS_TYPE_F64, PS_TYPE_C32, PS_TYPE_C64 };
+
+    psLogMsg(__func__,PS_LOG_INFO,"#546 - psImageAlloc shall allocate memory for a psImage structure");
+
+    for (unsigned int t=0;t<types;t++) {
+        psLogMsg(__func__,PS_LOG_INFO,"Testing psImage with type %xh",type[t]);
+
+        for (unsigned int i=0;i<sizes;i++) {
+
+            image = psImageAlloc(numCols[i],numRows[i],type[t]);
+
+            if (image == NULL) {
+                if (numRows[i] == 0 || numCols[i] == 0) {
+                    continue;
+                }
+                psError(__func__,"psImageAlloc returned NULL for type %x, size %dx%d.",
+                        type[t], numCols[i], numRows[i]);
+                psFree(image);
+                return 1;
+            }
+
+            if (image->type.dimen != PS_DIMEN_IMAGE || image->type.type != type[t]) {
+                psError(__func__,"psImageAlloc allocated wrong dimen/type (%d/%d), should be "
+                        "PS_IMAGE_DIMEN/%d", image->type.dimen, image->type.type, type[t]);
+                psFree(image);
+                return 2;
+            }
+
+            if (image->numCols != numCols[i] || image->numRows != numRows[i]) {
+                psError(__func__,"psImageAlloc allocated wrong size %dx%d, should be %dx%d (type = %d)",
+                        image->numCols, image->numRows, numCols[i], numRows[i],type[t]);
+                psFree(image);
+                return 3;
+            }
+
+            if (image->col0 != 0 || image->row0 != 0) {
+                psError(__func__,"psImageAlloc returned row0/col0 of %d/%d.  Should be 0/0.",
+                        image->row0, image->row0);
+                psFree(image);
+                return 4;
+            }
+
+            if (image->parent != NULL) {
+                psError(__func__,"psImageAlloc returned non-NULL parent");
+                psFree(image);
+                return 5;
+            }
+
+            if (image->nChildren != 0) {
+                psError(__func__,"psImageAlloc returned non-zero number of children");
+                psFree(image);
+                return 6;
+            }
+
+            if (image->children != NULL) {
+                psError(__func__,"psImageAlloc returned non-NULL children vector");
+                psFree(image);
+                return 7;
+            }
+
+            switch (type[t]) {
+            case PS_TYPE_U16: {
+                    unsigned int rows = numRows[i];
+                    unsigned int cols = numCols[i];
+
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            image->data.U16[r][c] = 2*c+r;
+                        }
+                    }
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            if (image->data.U16[r][c] != 2*c+r) {
+                                psError(__func__,"Could not set all pixels in uint16 image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_F32: {
+                    unsigned int rows = numRows[i];
+                    unsigned int cols = numCols[i];
+
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            image->data.F32[r][c] = 2.0f*c+r;
+                        }
+                    }
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            if (fabsf(image->data.F32[r][c] - (2.0f*c+r)) > FLT_EPSILON) {
+                                psError(__func__,"Could not set all pixels in float image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_F64: {
+                    unsigned int rows = numRows[i];
+                    unsigned int cols = numCols[i];
+
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            image->data.F64[r][c] = 2.0f*c+r;
+                        }
+                    }
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            if (fabs(image->data.F64[r][c] - (2.0f*c+r)) > DBL_EPSILON) {
+                                psError(__func__,"Could not set all pixels in double image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_C32: {
+                    unsigned int rows = numRows[i];
+                    unsigned int cols = numCols[i];
+
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            image->data.C32[r][c] = r + I * c;
+                        }
+                    }
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            if (fabsf(crealf(image->data.C32[r][c]) - r) > FLT_EPSILON ||
+                                    fabsf(cimagf(image->data.C32[r][c]) - c) > FLT_EPSILON ) {
+                                psError(__func__,"Could not set all pixels in complex image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            default: {
+                    // ignore type and just use as byte bucket.
+                    unsigned int rows = numRows[i];
+                    unsigned int cols = numCols[i]*PSELEMTYPE_SIZEOF(type[t]);
+
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            image->data.U8[r][c] = (uint8_t)(r + c);
+                        }
+                    }
+                    for (int r=0;r<rows;r++) {
+                        for (int c=0;c<cols;c++) {
+                            if (image->data.U8[r][c] != (uint8_t)(r + c)) {
+                                psError(__func__,"Could not set all pixels in image (type=%d) at (%d,%d)",
+                                        type[t],c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+            }
+
+            // #548: Verify no memory leaks or corruption are detected after a valid psImage structure with no
+            // children is freed.
+            psFree(image);
+        }
+    }
+
+    // #548: Verify program execution doesn't stop, if the input psImage structure pointer is null.
+    psFree(NULL);
+
+    // #548: Verify no memory leaks or corruption are detected after a valid psImage structure with multiple
+    // children isfreed.
+    image = psImageAlloc(100,100,PS_TYPE_F32);
+    psImageSubset(NULL,image,50,50,0,0);
+    psImageSubset(NULL,image,50,50,20,20);
+
+    psFree(image);
+
+    return 0;
+}
+
+// #547: psImageSubset shall create child image of a specified size from a parent psImage structure
+int testImageSubset(void)
+{
+    psImage preSubsetStruct;
+    psImage* original;
+    psImage* subset1 = NULL;
+    psImage* subset2 = NULL;
+    psImage* subset3 = NULL;
+    int c = 128;
+    int r = 256;
+
+    original = psImageAlloc(c,r,PS_TYPE_U32);
+    for (int row=0;row<r;row++) {
+        for (int col=0;col<c;col++) {
+            original->data.F32[row][col] = row*1000+col;
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"memcpy(&preSubsetStruct,original,sizeof(psImage));");
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    psLogMsg(__func__,PS_LOG_INFO,"subset1 = psImageAlloc(c/4,r/4,PS_TYPE_U8);");
+    subset1 = psImageAlloc(c/4,r/4,PS_TYPE_U8);
+
+    psLogMsg(__func__,PS_LOG_INFO,"subset2 = psImageSubset(subset1,original,c/2,r/2,c/4,r/4);");
+    subset2 = psImageSubset(subset1,original,c/2,r/2,c/4,r/4);
+
+    psLogMsg(__func__,PS_LOG_INFO,"subset3 = psImageSubset(NULL,original,c/2,r/2,0,0);");
+    subset3 = psImageSubset(NULL,original,c/2,r/2,0,0);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure is equal to the input psImage "
+             "structure parameter out, if input parameter out is specified.");
+
+    if (subset1 != subset2 || subset2 == NULL) {
+        psError(__func__,"psImageSubset didn't recycle the psImage given");
+        return 1;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify a new psImage structure is created, if input parameter out is set "
+             "to null.");
+
+    if (subset3 == NULL) {
+        psError(__func__,"psImageSubset output was NULL for subset3.");
+        return 2;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure contains expected values in the "
+             "row member, if the input psImage structure image contains known values.");
+
+    for (int row=0;row<r/2;row++) {
+        for (int col=0;col<c/2;col++) {
+            if (subset2->data.U32[row][col] != original->data.U32[row+r/4][col+c/4]) {
+                psError(__func__,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row+r/4][col+c/4]);
+                return 3;
+            }
+            if (subset3->data.U32[row][col] != original->data.U32[row][col]) {
+                psError(__func__,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row][col]);
+                return 4;
+            }
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure members nrow and ncol are equal to "
+             "the input parameter nrow and ncol respectively.");
+
+    if (subset3->numCols != c/2 || subset3->numRows != r/2) {
+        psError(__func__,"psImageSubset output size was not proper(%dx%d, should be %dx%d).",
+                subset3->numCols, subset3->numRows, c/2,r/2);
+        return 5;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member type is equal to the input "
+             "psImage structure member type.");
+
+    if (subset2->type.type != PS_TYPE_U32) {
+        psError(__func__,"psImageSubset output type was not proper(%d, should be %d).",
+                subset2->type.type, PS_TYPE_U32);
+        return 6;
+    }
+    if (subset3->type.type != PS_TYPE_U32) {
+        psError(__func__,"psImageSubset output type was not proper(%d, should be %d).",
+                subset3->type.type, PS_TYPE_U32);
+        return 7;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure members row0 and col0 are equal to "
+             "the input parameters row0 and col0 respectively.");
+
+    if (subset2->col0 != c/4 || subset2->row0 != r/4) {
+        psError(__func__,"psImageSubset didn't set col0/row0 for subset2 (%d/%d, should be %d/%d).",
+                subset2->col0,subset2->row0,c/4,r/4);
+        return 8;
+    }
+    if (subset3->col0 != 0 || subset3->row0 != 0) {
+        psError(__func__,"psImageSubset didn't set col0/row0 for subset3 (%d/%d, should be %d/%d).",
+                subset3->col0,subset3->row0,0,0);
+        return 9;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member parent is equal to the "
+             "input psImage structure pointer image.");
+
+    if (subset2->parent != original || subset3->parent != original) {
+        psError(__func__,"psImageSubset didn't set parent.");
+        return 10;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member Nchildren is equal to "
+             "zero.");
+
+    if (subset2->nChildren != 0 || subset3->nChildren != 0) {
+        psError(__func__,"psImageSubset didn't set nChildren to zero.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member children is null.");
+
+    if (subset2->children != NULL || subset3->children != NULL) {
+        psError(__func__,"psImageSubset didn't set children to NULL.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the input psImage structure image only has the following members "
+             "changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure "
+             "out at parent[Nchildren-1].");
+
+    if (original->nChildren != preSubsetStruct.nChildren+2) {
+        psError(__func__,"psImageSubset didn't increment nChildren by one per subset.");
+        return 12;
+    }
+    if (original->children[0] != subset2 || original->children[1] != subset3) {
+        psError(__func__,"psImageSubset didn't properly store the children pointers.");
+        return 13;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameter image is null. Also verified the input "
+             "psImage structure is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,NULL,c/2,r/2,0,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when input image was NULL.");
+        return 14;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             " execution doesn't stop, if the input parameters nrow and/or ncol are zero. Also verify "
+             "input psImage structure is not modified.");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,0,0,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when numRows=0.");
+        return 15;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,0,r/2,0,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when numCols=0.");
+        return 16;
+    }
+    if (memcmp(original,&preSubsetStruct,sizeof(psImage)) != 0) {
+        psError(__func__,"psImageSubset changed the original struct though it failed to subset.");
+        return 17;
+    }
+
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameters row0 and col0 are not within the range of "
+             "values of psImage structure image.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,c,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via cols).");
+        return 18;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,0,r);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via rows).");
+        return 19;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,-1,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (col0=-1).");
+        return 20;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,0,-1);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (row0=-1).");
+        return 21;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop if the input parameters nrow, ncol, row0 and col0 specify a range of "
+             "data not within the input psImage structure image.  Also verify the input psImage structure "
+             "is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,c/2,0);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via rows).");
+        return 22;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,0,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via cols).");
+        return 23;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,original,c/2,r/2,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via row+cols).");
+        return 24;
+    }
+
+    psLogMsg(__func__, PS_LOG_INFO, "psImageFreeChildren shall deallocate any children images of a "
+             "psImage structure");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    psImageFreeChildren(original);
+
+    // Verify the returned psImage structure member Nchildren is set to zero.
+    if (original->nChildren != 0) {
+        psError(__func__,"psImageFreeChildren didn't set nChildren to zero.");
+        return 25;
+    }
+
+    // Verify the returned psImage structure member children pointer is set to null.
+    if (original->children != NULL) {
+        psError(__func__,"psImageFreeChildren didn't set children ptr to NULL.");
+        return 26;
+    }
+
+    //Verify the returned psImage structure members type, nrow, ncol, row0, col0, rows and parent are not
+    // modified.
+    if (preSubsetStruct.numRows != original->numRows ||
+            preSubsetStruct.numCols != original->numCols ||
+            preSubsetStruct.row0 != original->row0 ||
+            preSubsetStruct.col0 != original->col0) {
+
+        psError(__func__,"psImageFreeChildren modified parent's non-children elements.");
+        return 27;
+    }
+
+    psFree(original);
+
+    return 0;
+}
+
+int testImageCopy(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    unsigned int c = 128;
+    unsigned int r = 256;
+
+    img = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = (psF32)(row+col);
+        }
+    }
+    img2 = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 0.0f;
+        }
+    }
+
+    img3 = psImageCopy(img2,img,PS_TYPE_F32);
+
+    // Verify the returned psImage structure pointer is equal to the input parameter output.
+    if (img2 != img3) {
+        psError(__func__,"the image given for recycled wasn't");
+        return 1;
+    }
+
+    // Verify the returned psImage structure member are equal to the values in
+    // the input psImage structure input.
+
+    #define testImageCopyType(IN,OUT) \
+    img = psImageRecycle(img,c,r,PS_TYPE_##IN); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##IN* imgRow = img->data.IN[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = (ps##IN)(row+col); \
+        } \
+    } \
+    img2 = psImageCopy(img2,img,PS_TYPE_##OUT); \
+    if (img2 == NULL) { \
+        psError(__func__,"psImageCopy failed to copy U8."); \
+        return 2; \
+    } \
+    for (unsigned int row=0;row<r;row++) { \
+        ps##IN* imgRow = img->data.IN[row]; \
+        ps##OUT* img2Row = img2->data.OUT[row]; \
+        for (unsigned int col=0;col<c;col++) { \
+            if (abs(imgRow[col] - (ps##IN)(row+col)) > 0.5) { \
+                psError(__func__,"Input image was changed at %d,%d!", \
+                        col,row); \
+                return 2; \
+            } \
+            if (abs(img2Row[col] - (ps##OUT)(imgRow[col])) > 0.5) { \
+                psError(__func__,"returned psImage values after copy don't match at %d,%d " \
+                        "(%d vs %d)",\
+                        col,row,img2Row[col], (ps##OUT)(imgRow[col])); \
+                return 2; \
+            } \
+        } \
+    }
+
+    #define testImageCopyTypes(IN) \
+    printf("to psF32\n"); \
+    testImageCopyType(IN,F32);\
+    printf("to psF64\n"); \
+    testImageCopyType(IN,F64); \
+    printf("to psU8\n"); \
+    testImageCopyType(IN,U8); \
+    printf("to psU16\n"); \
+    testImageCopyType(IN,U16); \
+    printf("to psU32\n"); \
+    testImageCopyType(IN,U32); \
+    printf("to psS8\n"); \
+    testImageCopyType(IN,S8);\
+    printf("to psS16\n"); \
+    testImageCopyType(IN,S16);\
+    printf("to psS32\n"); \
+    testImageCopyType(IN,S32);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU8");
+    testImageCopyTypes(U8);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU16");
+    testImageCopyTypes(U16);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU32");
+    testImageCopyTypes(U32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS8");
+    testImageCopyTypes(S8);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS16");
+    testImageCopyTypes(S16);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS32");
+    testImageCopyTypes(S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psF32");
+    testImageCopyTypes(F32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psF64");
+    testImageCopyTypes(F64);
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if the input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    img3 = psImageCopy(NULL,NULL,PS_TYPE_F32);
+    if (img3 != NULL) {
+        psError(__func__,"psImageCopy didn't return NULL when input image was NULL.");
+        return 3;
+    }
+
+    psFree(img);
+    psFree(img2);
+
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/image/tst_psImageExtraction.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageExtraction.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageExtraction.c	(revision 1553)
@@ -0,0 +1,235 @@
+/** @file  tst_psImageExtraction.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-06 22:34:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+#include<stdlib.h>
+
+#include "psTest.h"
+#include "pslib.h"
+#include "psType.h"
+
+static int testImageSlice( void );
+
+testDescription tests[] = {
+                              {
+                                  testImageSlice, 571, "psImageSlice", 0, false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main( int argc, char* argv[] )
+{
+    return ! runTestSuite( stderr, "psImage", tests, argc, argv );
+}
+
+int testImageSlice( void )
+{
+    const int r = 1000;
+    const int c = 2000;
+    const int m = r / 2;
+    const int n = r / 4;
+    psVector* out = NULL;
+    psImage* image = psImageAlloc( c, r, PS_TYPE_F32 );
+    psVector* positions = psVectorAlloc( r, PS_TYPE_U32 );
+    psImage* mask = psImageAlloc( c, r, PS_TYPE_MASK );
+    psStats* stat = psStatsAlloc( PS_STAT_SAMPLE_MEDIAN );
+
+    /*
+        This function shall extract pixels from a specified region of a psImage
+        structure into a vector using a specified statistical method.
+
+        Verify the returned psVector structure contains expected data, if the 
+        input psImage input has known data and the psStats structure specifies 
+        a known statistical method. At least two different statistical methods 
+        should be used within a valid range of psImage data. Allow for a delta 
+        when comparing results to allow for testing a different platforms. Two 
+        cases should be used for each possible direction. Data region cases 
+        should include 0x0, 1x1, Nx1, 1xN, NxN, MxN
+     
+     */
+
+    for ( int row = 0;row < r;row++ ) {
+        psF32* imageRow = image->data.F32[ row ];
+        psMaskType* maskRow = image->data.V[ row ];
+        psF32 rowOffset = ( psF32 ) row / ( psF32 ) r;
+        for ( int col = 0;col < c;col++ ) {
+            imageRow[ col ] = ( psF32 ) col + rowOffset;
+            maskRow[ col ] = 0;
+        }
+    }
+
+    // test MxN case
+
+    #define PSIMAGESLICE_TEST1(M,N,DIRECTION,TRUTH_SIZE,TRUTHPIX_X,TRUTHPIX_Y,TESTNUM) \
+    out = psImageSlice(out,positions,image,mask,1,c/10,r/10,M,N,DIRECTION,stat); \
+    \
+    if (out->n != TRUTH_SIZE) { \
+        psError(__func__,"Number of results is wrong (%d, not %d)", \
+                out->n,n); \
+        return TESTNUM*4+1; \
+    } \
+    \
+    if (positions->n != TRUTH_SIZE) { \
+        psError(__func__,"Number of results for positions vector is wrong (%d, not %d)", \
+                out->n,n); \
+        return TESTNUM*4+2; \
+    } \
+    \
+    for (int i=0;i<out->n;i++) { \
+        if (abs(out->data.F64[i]-image->data.F32[r/10+TRUTHPIX_Y][c/10+TRUTHPIX_X]) > 1.0/(psF32)r) { \
+            psError(__func__,"Improper result at position %d.",i); \
+            return TESTNUM*4+3; \
+        } \
+        if (DIRECTION == PS_CUT_X_POS || DIRECTION == PS_CUT_X_NEG) { \
+            if (positions->data.U32[i] != c/10+TRUTHPIX_X) { \
+                psError(__func__,"Improper positions (%d vs %d) result @ %d.", \
+                        positions->data.U32[i],c/10+TRUTHPIX_X,i); \
+                return TESTNUM*4+4; \
+            } \
+        } else { \
+            if (positions->data.U32[i] != r/10+TRUTHPIX_Y) { \
+                psError(__func__,"Improper positions (%d vs %d) result @ %d.", \
+                        positions->data.U32[i],r/10+TRUTHPIX_Y,i); \
+                return TESTNUM*4+4; \
+            } \
+        } \
+    }
+
+    // test MxN case
+    PSIMAGESLICE_TEST1( m, n, PS_CUT_X_POS, m, i, n / 2, 0 );
+    PSIMAGESLICE_TEST1( m, n, PS_CUT_X_NEG, m, m - 1 - i, n / 2, 1 );
+    PSIMAGESLICE_TEST1( m, n, PS_CUT_Y_POS, n, m / 2, i, 2 );
+    PSIMAGESLICE_TEST1( m, n, PS_CUT_Y_NEG, n, m / 2, n - 1 - i, 3 );
+
+    // test Mx1 case
+    PSIMAGESLICE_TEST1( m, 1, PS_CUT_X_POS, m, i, 0, 4 );
+    PSIMAGESLICE_TEST1( m, 1, PS_CUT_X_NEG, m, m - 1 - i, 0, 5 );
+    PSIMAGESLICE_TEST1( m, 1, PS_CUT_Y_POS, 1, m / 2, 0, 6 );
+    PSIMAGESLICE_TEST1( m, 1, PS_CUT_Y_NEG, 1, m / 2, 0, 7 );
+
+    // test 1xN case
+    PSIMAGESLICE_TEST1( 1, n, PS_CUT_X_POS, 1, 0, n / 2, 8 );
+    PSIMAGESLICE_TEST1( 1, n, PS_CUT_X_NEG, 1, 0, n / 2, 9 );
+    PSIMAGESLICE_TEST1( 1, n, PS_CUT_Y_POS, n, 0, i, 10 );
+    PSIMAGESLICE_TEST1( 1, n, PS_CUT_Y_NEG, n, 0, n - 1 - i, 11 );
+
+    // test 1x1 case
+    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_X_POS, 1, 0, 0, 12 );
+    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_X_NEG, 1, 0, 0, 13 );
+    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_Y_POS, 1, 0, 0, 14 );
+    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_Y_NEG, 1, 0, 0, 15 );
+
+    /*
+       Verify the returned psVector structure pointer is null and program 
+       execution doesn't stop, if input psImage input is null.
+
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, NULL, NULL, 0, c / 10, r / 10, 1, 1, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving a NULL image, psImageSlice didn't return NULL as expected" );
+        return 101;
+    }
+
+
+    /*
+       Verify the returned psVector structure pointer is null and program 
+       execution doesn't stop, if input psStats stats is null.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, 1, 1, PS_CUT_X_POS, NULL );
+    if ( out != NULL ) {
+        psError( __func__, "Giving a NULL stat struct, psImageSlice didn't return NULL as expected" );
+        return 102;
+    }
+
+    /*
+
+       Verify the returned psVector structure pointer is null and program 
+       executions doesn't stop, if the input direction is not set to one of 
+       the two valid values.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, 1, 1, 5, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving a bogus direction flag, psImageSlice didn't return NULL as expected" );
+        return 103;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program 
+       execution doesn't stop, if the input nrow and/or ncol are zero.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, 0, 0, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving a 0x0 region, psImageSlice didn't return NULL as expected" );
+        return 104;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program 
+       execution doesn't stop, if the inputs row, col, nrow, ncol specify a 
+       regions of data that is not within the input psImage structure.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c + 1, r / 10, 1, 1, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving an invalid x position, psImageSlice didn't return NULL as expected" );
+        return 105;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r + 1, 1, 1, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving an invalid y position, psImageSlice didn't return NULL as expected" );
+        return 106;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, c, 1, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving an invalid numCols, psImageSlice didn't return NULL as expected" );
+        return 107;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, 1, r, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving an invalid numRows, psImageSlice didn't return NULL as expected" );
+        return 108;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program 
+       execution doesn't stop, if the input psStat structure member options is 
+       zero which indicates no statistic method specified.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    stat->options = 0;
+    out = psImageSlice( out, NULL, image, mask, 1, c / 10, r / 10, 1, 1, PS_CUT_X_POS, stat );
+    if ( out != NULL ) {
+        psError( __func__, "Giving an invalid numRows, psImageSlice didn't return NULL as expected" );
+        return 109;
+    }
+
+    psFree( image );
+    psFree( positions );
+    psFree( mask );
+    psFree( out );
+    psFree( stat );
+
+    return 0;
+
+}
+
Index: /tags/rel2_1/psLib/test/image/tst_psImageFFT.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageFFT.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageFFT.c	(revision 1553)
@@ -0,0 +1,378 @@
+/** @file  tst_psImageFFT.c
+ *
+ *  @brief Contains the tests for psFFT.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+
+#include "psTest.h"
+#include "pslib.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (unsigned int row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (unsigned int col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static int testImageFFT(void);
+static int testImageRealImaginary(void);
+static int testImageComplex(void);
+static int testImageConjugate(void);
+static int testImagePowerSpectrum(void);
+
+testDescription tests[] = {
+                              {
+                                  testImageFFT,600,"psImageFFT",0,false
+                              },
+                              {
+                                  testImageRealImaginary,601,"psImageRealImaginary",0,false
+                              },
+                              {
+                                  testImageComplex,602,"psImageComplex",0,false
+                              },
+                              {
+                                  testImageConjugate,603,"psImageConjugate",0,false
+                              },
+                              {
+                                  testImagePowerSpectrum,604,"psImagePowerSpectrum",0,false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if (! runTestSuite(stderr,"psFFT",tests,argc,argv) ) {
+        psAbort(__FILE__,"One or more tests failed");
+    }
+    return 0;
+}
+
+int testImageFFT(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    unsigned int m = 128;
+    unsigned int n = 64;
+
+    /*
+    1. assign a image to a radial sinisoid
+    2. perform a forward transform
+    3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    4. perform a reverse transform
+    5. compare to original (should be equal to within a reasonable error)
+    */
+
+    // 1. assign a image to a radial sinisoid
+    GENIMAGE(img,m,n,F32, sinf((32.0f-row)/16.0f*M_PI)+sinf((64.0f-col)/32.0f*M_PI));
+
+    // 2. perform a forward transform
+    img2 = psImageFFT(NULL,img,PS_FFT_FORWARD);
+    if (img2->type.type != PS_TYPE_C32) {
+        psError(__func__,"FFT didn't produce complex values?");
+        return 1;
+    }
+
+    // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    for (unsigned int row=0;row<n;row++) {
+        psC32* img2Row = img2->data.C32[row];
+        for (unsigned int col=0;col<m;col++) {
+            psF32 mag = cabsf(img2Row[col])/m/n;
+            if (mag > 0.1f) {
+                // must be (0,1) or (0,n-1) or (1,0) or (n-1,0)
+                if (! (col == 0 && (row == 1 || row == n-1))
+                        && ! (row == 0 && (col==1 || col == n-1)) ) {
+                    psError(__func__,"Result invalid at %d,%d (%.2f)",col,row,mag);
+                }
+            } else
+                if ( (col == 0 && (row == 1 || row == n-1))
+                        || (row == 0 && (col==1 || col == n-1)) ) {
+                    psError(__func__,"Result invalid at %d,%d (%.2f)",col,row,mag);
+                }
+        }
+    }
+
+    // 4. perform a reverse transform
+    img3 = psImageFFT(NULL,img2,PS_FFT_REVERSE);
+    if (img3->type.type != PS_TYPE_C32) {
+        psError(__func__,"FFT didn't produce complex values?");
+        return 4;
+    }
+
+    for (unsigned int row=0;row<n;row++) {
+        psC32* img3Row = img3->data.C32[row];
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned int col=0;col<m;col++) {
+            psF32 pixel = creal(img3Row[col])/m/n;
+            if (fabsf(pixel-imgRow[col]) > 0.1) {
+                psError(__func__,"Reverse FFT didn't gime original image back (%d,%d %.2f vs %.2f)",
+                        col,row,pixel,imgRow[col]);
+                return 5;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+
+    return 0;
+}
+
+int testImageRealImaginary(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    unsigned int m = 128;
+    unsigned int n = 64;
+
+    /*
+    1. create a C32 complex vector with distinctly different real and imaginary parts.
+    2. call psImageReal and psImageImaginary
+    3. compare results to the real/imaginary components of input
+    */
+
+    // 1. create a C32 complex vector with distinctly different real and imaginary parts.
+    GENIMAGE(img,m,n,C32, row + I * col);
+
+    // 2. call psImageReal and psImageImaginary
+    img2 = psImageReal(img2,img);
+    if (img2 == NULL) {
+        psError(__func__,"psImageReal returned a NULL?");
+        return 1;
+    }
+    if (img2->type.type != PS_TYPE_F32) {
+        psError(__func__,"psImageReal returned a wrong type (%d)?",
+                img2->type.type);
+        return 2;
+    }
+
+    img3 = psImageImaginary(img3,img);
+    if (img3 == NULL) {
+        psError(__func__,"psImageImaginary returned a NULL?");
+        return 3;
+    }
+    if (img3->type.type != PS_TYPE_F32) {
+        psError(__func__,"psImageImaginary returned a wrong type (%d)?",
+                img3->type.type);
+        return 4;
+    }
+
+    // 3. compare results to the real/imaginary components of input
+    for (unsigned int row=0;row<n;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        psF32* img3Row = img3->data.F32[row];
+        for (unsigned int col=0;col<m;col++) {
+            if (fabsf(img2Row[col] - row) > FLT_EPSILON) {
+                psError(__func__,"psImageReal didn't return the real portion at n=%d",
+                        n);
+                return 5;
+            }
+            if (fabsf(img3Row[col] - col) > FLT_EPSILON) {
+                psError(__func__,"psImageImaginary didn't return the imag portion at n=%d",
+                        n);
+                return 6;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+
+    return 0;
+}
+
+int testImageComplex(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    unsigned int m = 128;
+    unsigned int n = 64;
+
+    /*
+    1. create two unique psF32 vectors of the same size
+    2. call psImageComplex
+    3. verify that the result is a psC32
+    4. call psImageReal and psImageImaginary on step 2 results
+    5. compare step 4 results to input.
+
+    6. create a psF32 and a psF64 vector of the same size
+    7. call psImageComplex
+    8. verify that an appropriate error occurred.
+
+    9. create two psf32 vectors of different sizes
+    10. call psImageComplex
+    11. verify thet an appropriate error occurred.
+    */
+
+    // 1. create two unique psF32 vectors of the same size
+    GENIMAGE(img,m,n,F32,row);
+    GENIMAGE(img2,m,n,F32,col);
+
+    // 2. call psImageComplex
+    img3 = psImageComplex(img3,img,img2);
+
+    // 3. verify that the result is a psC32
+    if (img3->type.type != PS_TYPE_C32) {
+        psError(__func__,"Image Type from psImageComplex is not complex? (%d)",
+                img3->type.type);
+        return 1;
+    }
+
+    // 4. call psImageReal and psImageImaginary on step 2 results (not needed, just use crealf/cimagf)
+    // 5. compare step 4 results to input.
+    for (unsigned int row=0;row<n;row++) {
+        psC32* img3Row = img3->data.C32[row];
+        for (unsigned int col=0;col<m;col++) {
+            if (fabsf(crealf(img3Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(img3Row[col]) - col) > FLT_EPSILON) {
+                psError(__func__,"psImageComplex result is invalid (%d,%d, %.2f+%.2fi)",
+                        col,row,crealf(img3Row[col]),cimagf(img3Row[col]));
+                return 2;
+            }
+        }
+    }
+
+    // 6. create a psF32 and a psF64 image of the same size
+    img2 = psImageRecycle(img2,m,n,PS_TYPE_F64);
+
+    // 7. call psImageComplex
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error (type mismatch).");
+    img3 = psImageComplex(img3,img,img2);
+    // 8. verify that an appropriate error occurred. (this partially has to be done via inspection)
+    if (img3 != NULL) {
+        psError(__func__,"psImageComplex returned a image though input types mismatched.");
+        return 3;
+    }
+
+    // 9. create two psf32 vectors of different sizes
+    img2 = psImageRecycle(img2,m/2,n,PS_TYPE_F32);
+
+    // 10. call psImageComplex
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error (size mismatch).");
+    img3 = psImageComplex(img3,img,img2);
+
+    // 11. verify thet an appropriate error occurred.
+    if (img3 != NULL) {
+        psError(__func__,"psImageComplex returned a image though input sizes mismatched.");
+        return 4;
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+
+    return 0;
+}
+
+int testImageConjugate(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    unsigned int m = 128;
+    unsigned int n = 64;
+
+    /*
+    1. create a psC32 with unique real and imaginary values.
+    2. call psImageConjugate
+    3. verify result is psC32
+    4. verify each value is conjugate of input (a+bi -> a-bi)
+    */
+
+    // 1. create a psC32 with unique real and imaginary values.
+    GENIMAGE(img,m,n,C32, row + I * col);
+
+    // 2. call psImageConjugate
+    img2 = psImageConjugate(img2,img);
+
+    // 3. verify result is psC32
+    if (img2->type.type != PS_TYPE_C32) {
+        psError(__func__,"the psImageConjugate didn't return a C32 image.");
+        return 1;
+    }
+
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    for (unsigned int row=0;row<n;row++) {
+        psC32* img2Row = img2->data.C32[row];
+        for (unsigned int col=0;col<m;col++) {
+            if (fabsf(crealf(img2Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(img2Row[col]) + col) > FLT_EPSILON) {
+                psError(__func__,"psImageComplex result is invalid (%d,%d, %.2f+%.2fi)",
+                        col,row,crealf(img2Row[col]),cimagf(img2Row[col]));
+                return 2;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+
+    return 0;
+}
+
+int testImagePowerSpectrum(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    unsigned int m = 128;
+    unsigned int n = 64;
+
+    /*
+    1. create a psC32 vector with unique real and imaginary components
+    2. call psImagePowerSpectrum
+    3. verify result is psF32
+    4. verify the values are the square of the absolute values of the original
+    */
+
+    // 1. create a psC32 vector with unique real and imaginary components
+    GENIMAGE(img,m,n,C32, row + I * col);
+
+    // 2. call psImagePowerSpectrum
+    img2 = psImagePowerSpectrum(img2,img);
+
+    // 3. verify result is psF32
+    if (img2->type.type != PS_TYPE_F32) {
+        psError(__func__,"the type was not PS_TYPE_F32.");
+        return 1;
+    }
+
+    // 4. verify the values are the square of the absolute values of the original
+    for (unsigned int row=0;row<n;row++) {
+        psC32* imgRow = img->data.C32[row];
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned int col=0;col<m;col++) {
+            psF32 power = cabs(imgRow[col]);
+            power *= power/n/n/m/m;
+
+            if (fabsf(img2Row[col] - power) > 2.0f*FLT_EPSILON) {
+                psError(__func__,"psImagePowerSpectrum result is invalid (%d,%d, %.2f vs %.2f)",
+                        col,row,img2Row[col],power);
+                return 2;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageIO.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageIO.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageIO.c	(revision 1553)
@@ -0,0 +1,332 @@
+/** @file  tst_psImageIO.c
+ *
+ *  @brief Contains the tests for psImageIO.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (unsigned int row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (unsigned int col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static int testImageRead(void);
+static int testImageWrite(void);
+
+testDescription tests[] = {
+                              {
+                                  testImageRead,567,"psImageReadSection",0,false
+                              },
+                              {
+                                  testImageWrite,569,"psImageWriteSection",0,false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if (! runTestSuite(stderr,"psImage",tests,argc,argv)) {
+        psAbort(__FILE__,"One or more tests failed");
+    }
+    return 0;
+}
+
+int testImageRead(void)
+{
+    int N = 256;
+    int M = 128;
+    psImage* image = NULL;
+
+    /*
+        This function shall open the specified FITS file, read the specified data
+        and place the data into a psImage structure. This function shall generate
+        an error message and return NULL if any of the input parameters are out of
+        range, image file doesn't exist or image is zero or one dimensional.
+     
+        Verify the returned psImage structure contains expected values, if the input
+        parameter filename specifies an available FITS file with known 2dimensional
+        data, input parameters col, row, ncol, nrow, z specify data range with the
+        FITS file. Cases should include 1x1, Nx1, 1xN, NxN and MxN sub images and
+        total FITS file image. (done in macro)
+     
+        Verify the returned psImage structure is equal to the input parameter
+        'output', if specified. (done in macro)
+     
+        */
+
+    /* generate FITS file to read */
+
+    #define testReadTypeSize(m, n, readM0, readN0, readM, readN, TYP, filename) \
+    { \
+        psImage* img = NULL; \
+        psImage* img2 = NULL; \
+        psImage* img3 = NULL; \
+        psImage* img4 = NULL; \
+        psImage* img_ref = NULL; \
+        \
+        GENIMAGE(img,m,n,TYP,row+2*col); \
+        img2 = psImageCopy(img2,img,PS_TYPE_##TYP); \
+        GENIMAGE(img3,m,n,TYP,row+2*col); \
+        psImageClip(img3,32.0,32.0,120.0,120.0); \
+        img4 = psImageCopy(img4,img3,PS_TYPE_##TYP); \
+        remove(filename); \
+        if (! psImageWriteSection(img3,0,0,1,NULL,0,filename)) { \
+            psError(__func__,"Failed to write test image %s",filename); \
+            return 1; \
+        } \
+        if (! psImageWriteSection(img,0,0,0,NULL,0,filename)) { \
+            psError(__func__,"Failed to write test image %s",filename); \
+            return 2; \
+        } \
+        if (! psImageWriteSection(img,0,0,1,NULL,1,filename)) { \
+            psError(__func__,"Failed to write test image %s",filename); \
+            return 3; \
+        } \
+        if (! psImageWriteSection(img3,0,0,0,NULL,1,filename)) { \
+            psError(__func__,"Failed to write test image %s",filename); \
+            return 4; \
+        } \
+        psFree(img); \
+        img_ref = img = psImageAlloc(2,2,PS_TYPE_F32); \
+        psFree(img3); \
+        img3 = NULL; \
+        img = psImageReadSection(img,readM0,readN0,readM,readN,0,NULL,0,filename); \
+        if (img_ref != img) { \
+            psError(__func__,"psImageReadSection didn't recycle the psImage?"); \
+            return 5; \
+        } \
+        img3 = psImageReadSection(img3,readM0,readN0,readM,readN,1,NULL,0,filename); \
+        if (img == NULL) { \
+            psError(__func__,"Failed to read test image %s",filename); \
+            return 6; \
+        } \
+        for (unsigned int row = readN0; row < readN; row++) { \
+            ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+            ps##TYP* img2Row = img2->data.TYP[row]; \
+            ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+            ps##TYP* img4Row = img4->data.TYP[row]; \
+            for (unsigned int col = readM0; col < readM; col++) { \
+                if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                    psError(__func__,"Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                    return 7; \
+                } \
+                if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                    psError(__func__,"Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                    return 8; \
+                } \
+            } \
+        } \
+        psFree(img); \
+        img = NULL; \
+        psFree(img3); \
+        img3 = NULL; \
+        img3 = psImageReadSection(img3,readM0,readN0,readM,readN,0,NULL,1,filename); \
+        img = psImageReadSection(img,readM0,readN0,readM,readN,1,NULL,1,filename); \
+        if (img == NULL) { \
+            psError(__func__,"Failed to read test image %s",filename); \
+            return 9; \
+        } \
+        for (unsigned int row = readN0; row < readN; row++) { \
+            ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+            ps##TYP* img2Row = img2->data.TYP[row]; \
+            ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+            ps##TYP* img4Row = img4->data.TYP[row]; \
+            for (unsigned int col = readM0; col < readM; col++) { \
+                if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                    psError(__func__,"Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                    return 10; \
+                } \
+                if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                    psError(__func__,"Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                    return 11; \
+                } \
+            } \
+        } \
+        psFree(img); \
+        psFree(img2); \
+        psFree(img3); \
+        psFree(img4); \
+    }
+
+    #define testReadType(TYP,filename) \
+    mkdir("tmpImages",0777); \
+    testReadTypeSize(1,1,0,0,1,1,TYP,"tmpImages/1x1_" filename); \
+    testReadTypeSize(M,1,M/4,0,M/2,1,TYP,"tmpImages/Mx1_" filename); \
+    testReadTypeSize(1,N,0,N/4,1,N/2,TYP,"tmpImages/1xN_" filename); \
+    testReadTypeSize(M,N,M/4,N/4,M/2,N/2,TYP,"tmpImages/MxN_" filename);
+
+    testReadType(U8,"U8.fits");
+    testReadType(S8,"S8.fits");
+    testReadType(S16,"S16.fits");
+    testReadType(U16,"U16.fits");
+    testReadType(S32,"S32.fits");
+    testReadType(U32,"U32.fits");
+    testReadType(F32,"F32.fits");
+    testReadType(F64,"F64.fits");
+
+    /*
+    Verify the returned psImage structure pointer is null, error log message is
+    generated and program execution doesn't stop, if input parameter filename
+    specifies a file that doesn't exist.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error as file doesn't exist.");
+    image = psImageReadSection(image,0,0,M,N,0,NULL,0,"foobar.fits");
+    if (image != NULL) {
+        psError(__func__,"Image returned though filename did not exist.");
+        return 12;
+    }
+
+    /*
+    Verify the returned psImage structure pointer is null, error log message is
+    generatedand program execution doesn't stop, if input parameter filename
+    is null.Verify the returned psImage structurepointer is null, error log
+    message is generated and program execution doesn't stop, if input
+    parameters col,row, ncol, nrow and/or z specify a data range which is not
+    within the data range of the FITS file.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error as filename is NULL.");
+    image = psImageReadSection(image,0,0,M,N,0,NULL,0,NULL);
+    if (image != NULL) {
+        psError(__func__,"Image returned though filename was NULL.");
+        return 13;
+    }
+
+    /*
+    Verify the returned psImage structure pointer is null, error log message is
+    generated and program execution doesn't stop,if input parameters extname
+    and/or extnum specify an extension which is not valid in the FITS file.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error as extnum is invalid.");
+    image = psImageReadSection(image,0,0,M,N,0,NULL,4,"tmpImages/MxN_F32.fits");
+    if (image != NULL) {
+        psError(__func__,"Image returned though extnum was invalid.");
+        return 14;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error as extname is invalid.");
+    image = psImageReadSection(image,0,0,M,N,0,"bogus",0,"tmpImages/MxN_F32.fits");
+    if (image != NULL) {
+        psError(__func__,"Image returned though extnum was invalid.");
+        return 15;
+    }
+
+    /*
+    Verify the returned psImage structure pointer is null, error log message is
+    generated and program execution doesn't stop,if input parameter filename
+    specifies a FITS file that is zero or one dimensional.
+
+    XXX
+    N.B: since I can't write anything but 2 or 3 dimensional image, I can't
+    do this programatically at this time.  I verified that this functionality
+    exists in the source code via inspection. (line 101 in psImageIO.c for v1.3)
+    -rdd
+    */
+
+    return 0;
+}
+
+int testImageWrite(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    int m = 64;
+    int n = 96;
+
+    /*
+    This function shall write the specified section within a psImage structure
+    to a FITS file. If the specifiedfile exists, then data should overwrite the
+    section to write. If the specified file doesn't exist, it shall be created.
+    If an extenstion is specified, then a basic primary header data unit shall
+    be created.
+    */
+
+    /*
+    Verify a FITS file named filename is generated and contains expected
+    values, if the input parameter input contains known data values, input
+    parameters col, row, ncol, nrow specify a valid data region within psImage
+    structure.
+
+    Verify a FITS file named filename is generated and contains a primary
+    header data unit with extension with expected values, if the input
+    parameter input contains known data values, input parameters col, row,
+    ncol, nrow specify a valid data region within psImage structure and
+    extname and/or extnum specify an extenstion to write.
+
+    N.B. : these are done in testImageRead tests, see above.
+    */
+
+    /*
+    Verify a FITS file named filename is overwritten and contains
+    expected values, if the input parameter input contains known data values,
+    input parameters col, row, ncol, nrow specify a valid data region within
+    psImage structure.
+    */
+
+    GENIMAGE(img,m,n,F32,0);
+    GENIMAGE(img2,m,n,F32,row+2*col);
+    mkdir("tmpImages",0777);
+    remove
+        ("writeTest.fits")
+        ;
+    if (! psImageWriteSection(img,0,0,0,NULL,0,"tmpImages/writeTest.fits")) {
+        psError(__func__,"Couldn't write writeTest.fits.");
+        return 14;
+    }
+    if (! psImageWriteSection(img2,0,0,0,NULL,0,"tmpImages/writeTest.fits")) {
+        psError(__func__,"Couldn't overwrite writeTest.fits.");
+        return 15;
+    }
+    psFree(img);
+    psFree(img2);
+
+    // Did it really overwrite the pixel values?  Let's read it in and see.
+    img = psImageReadSection(NULL,0,0,m,n,0,NULL,0,"tmpImages/writeTest.fits");
+    if (img == NULL) {
+        psError(__func__,"Could not read in writeTest.fits.");
+        return 16;
+    }
+    for (unsigned int row=0;row<n;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned int col=0;col<m;col++) {
+            if (fabsf(imgRow[col] - (row+2*col)) > FLT_EPSILON) {
+                psError(__func__,"The image values were not overwritten at %d,%d (%.2f vs %.2f)",
+                        col,row,imgRow[col],(row+2*col));
+                return 17;
+            }
+        }
+    }
+
+    psFree(img);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageManip.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageManip.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageManip.c	(revision 1553)
@@ -0,0 +1,1239 @@
+/** @file  tst_psImageManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-08-12 03:11:08 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>                    // for memset
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib.h"
+#include "psType.h"
+
+static int testImageClip(void);
+static int testImageClipNAN(void);
+static int testImageClipComplexRegion(void);
+static int testImageOverlay(void);
+static int testImageRebin(void);
+static int testImageRoll(void);
+static int testImageRotate(void);
+
+testDescription tests[] = {
+                              {
+                                  testImageClip,571,"psImageClip",0,false
+                              },
+                              {
+                                  testImageClipNAN,572,"psImageClipNAN",0,false
+                              },
+                              {
+                                  testImageClipComplexRegion,673,"psImageClipComplexRegion",0,false
+                              },
+                              {
+                                  testImageOverlay,573,"psImageOverlay",0,false
+                              },
+                              {
+                                  testImageRebin,559,"psImageRebin",0,false
+                              },
+                              {
+                                  testImageRoll,562,"psImageRoll",0,false
+                              },
+                              {
+                                  testImageRotate,560,"psImageRotate",0,false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+
+int testImageClip(void)
+{
+    psImage* img = NULL;
+    unsigned int c = 128;
+    unsigned int r = 256;
+    psF64 min;
+    psF64 max;
+    int numClipped = 0;
+    int retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClip shall limit the minimum and maximum data value within a psImage structure");
+
+    /*
+
+        psImageClip shall limit the minimum and maximum data value within a
+        psImage structure to a specified min and max value.
+
+        Verify the returned integer is equal to the number of pixels clipped,
+        if the input psImage structure contains known values and input parameters
+        min and max have know values.
+
+        Verify the psImage structure specified by the input parameter input is
+        modified to contain the expected values, if the input psImage structure
+        contains known values, min and max are specified and vmin and vmax
+        parameters are known.
+
+        Verify the retuned integer is zero, psImage structure input is unmodified
+        and program executions doesn't stop, if input parameter psImage structure
+        pointer is null.
+
+        Verify the retuned integer is zero, psImage structure input is unmodified
+        and program executions doesn't stop, if input parameter min is larger than max.
+    */
+
+    // create image
+    #define testImageClipByType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned int row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned int col=0;col<c;col++) { \
+            imgRow[col] = (ps##datatype)(row+col); \
+        } \
+    } \
+    min = (psF64)r/2.0; \
+    max = (psF64)r; \
+    \
+    retVal = psImageClip(img,min,(double)PS_MIN_##datatype,max,(double)PS_MAX_##datatype); \
+    \
+    numClipped = 0; \
+    for (unsigned int row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned int col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+col); \
+            if (value < min) { \
+                numClipped++; \
+                value = PS_MIN_##datatype; \
+            } else if (value > max) { \
+                numClipped++; \
+                value = PS_MAX_##datatype; \
+            } \
+            if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(__func__,"Pixel value is not as expected (%g vs %g) at %u,%u", \
+                        (psF64)imgRow[col],(psF64)value,col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(__func__,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    #define testImageClipByComplexType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned int row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned int col=0;col<c;col++) { \
+            imgRow[col] = (ps##datatype)(row+I*col); \
+        } \
+    } \
+    min = (float)r/2.0f; \
+    max = (float)r; \
+    \
+    retVal = psImageClip(img,min,-1.0f,max,-2.0f); \
+    \
+    numClipped = 0; \
+    for (unsigned int row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned int col=0;col<c;col++) { \
+            ps##datatype value = row+I*col; \
+            if (cabs(value) < min) { \
+                numClipped++; \
+                value = -1.0f; \
+            } else if (cabs(value) > max) { \
+                numClipped++; \
+                value = -2.0f; \
+            } \
+            if (fabsf(creal(imgRow[col])-creal(value)) > FLT_EPSILON || \
+                    fabsf(cimag(imgRow[col])-cimag(value)) > FLT_EPSILON) { \
+                psError(__func__,"Pixel value is not as expected (%.2f+%.2fi vs %.2f+%.2fi) at %u,%u", \
+                        creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(__func__,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of F64 imagery");
+    testImageClipByType(F64);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of F32 imagery");
+    testImageClipByType(F32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S32 imagery");
+    testImageClipByType(S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S16 imagery");
+    testImageClipByType(S16);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S8 imagery");
+    testImageClipByType(S8);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U32 imagery");
+    testImageClipByType(U32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U16 imagery");
+    testImageClipByType(U16);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U8 imagery");
+    testImageClipByType(U8);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of C32 imagery");
+    testImageClipByComplexType(C32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of C64 imagery");
+    testImageClipByComplexType(C64);
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter psImage structure
+    // pointer is null.
+    retVal = psImageClip(NULL,min,-1.0f,max,-2.0f);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter min is larger than max.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (max<min)");
+    retVal = psImageClip(img,max,-1.0f,min,-2.0f);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for clips when max < min.");
+        return 4;
+    }
+
+    return 0;
+}
+
+int testImageClipNAN(void)
+{
+    psImage* img = NULL;
+    unsigned int c = 128;
+    unsigned int r = 256;
+    int numClipped = 0;
+    int retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+    /*
+        psImageClipNaN shall modify a psImage structure with pixel values set
+        to NaN to a value specified as an input parameter.
+
+        Verify the returned integer is equal to the number of pixels modified
+        and the psImage is modified at locations where NaN pixels where
+        located to the value specified in the input parameter value.
+
+        Verify the returned integer is zero and program execution doesn't stop,
+        if the input parameter psImage structure pointer is null.
+    */
+
+    // create image
+    #define testImageClipNaNByType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            if (row == col) { \
+                imgRow[col] = NAN; \
+            } else if (row+1 == col) { \
+                imgRow[col] = INFINITY; \
+            } else { \
+                imgRow[col] = (ps##datatype)(row+col); \
+            } \
+        } \
+    } \
+    \
+    retVal = psImageClipNaN(img,-1.0f); \
+    \
+    numClipped = 0; \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+col); \
+            if ( (row == col) || (row+1 == col) ) { \
+                numClipped++; \
+                value = -1.0; \
+            } \
+            if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(__func__,"Pixel value is not as expected (%f vs %f) at %d,%d", \
+                        imgRow[col],value,col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(__func__,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    testImageClipNaNByType(F32);
+    testImageClipNaNByType(F64);
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter psImage structure
+    // pointer is null.
+    retVal = psImageClipNaN(NULL,-1.0f);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+    return 0;
+}
+
+int testImageClipComplexRegion(void)
+{
+    psImage* img = NULL;
+    unsigned int c = 1024;
+    unsigned int r = 2048;
+    int numClipped = 0;
+    int retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+    /*
+    1. Create a complex image with a wide range of complex values
+
+    2. call psImageClipComplexRegion with min and max where there is at least 
+       2 pixels in the image above) that is:
+        a) real(p) < real(min) && complex(p) < complex(min),
+        b) real(p) < real(min) && complex(min) < complex(p) < complex(max)
+        c) real(min) < real(p) < real(max) && complex(p) < complex(min)
+        d) real(min) < real(p) < real(max) && complex(min) < complex(p) < complex(max)
+        e) real(p) > real(max) && complex(min) < complex(p) < complex(max)
+        f) real(pmin) < real(p) < real(max) && complex(p) > complex(max)
+        g) real(p) > real(max) && complex(p) > complex(max)
+        h) real(p) < real(min) && complex(p) > complex(max)
+        i) real(p) > real(max) && complex(p) < complex(min)
+
+    3. verify that All pixels in case (a), (b), and (c) have the value vmin
+
+    4. verify that all pixels in case (d) are unchanged from input
+
+    5. verify that all pixels in case (e), (f), (g), (h), and (i) have the 
+       value vmax
+
+    */
+
+    #define testImageClipComplexByType(datatype,MIN,MAX) /* datatype must be complex */ \
+    /* create image */ \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = row+I*col; \
+        } \
+    } \
+    \
+    retVal = psImageClipComplexRegion(img,MIN,-1.0-1.0*I,MAX,-2.0-2.0*I); \
+    \
+    numClipped = 0; \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+I*col); \
+            if ( (row > creal(MAX)) || (col > cimag(MAX)) ) { \
+                numClipped++; \
+                value = -2.0-2.0*I; \
+            } else if ((row < creal(MIN)) || (col < cimag(MIN)) ) { \
+                numClipped++; \
+                value = -1.0-1.0*I; \
+            } \
+            if (cabs(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(__func__,"Pixel value is not as expected (%g%+gi vs %g%+gi) at %d,%d", \
+                        creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(__func__,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    complex double min = ((double)r)/5.0+I*((double)c)/4.0;
+    complex double max = ((double)r)/3.0+I*((double)c)/2.0;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping at %g%+gi to %g%+gi for psC32",
+             creal(min),cimag(min),creal(max),cimag(max));
+
+    testImageClipComplexByType(C32,min,max);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping at %g%+gi to %g%+gi for psC64",
+             creal(min),cimag(min),creal(max),cimag(max));
+    testImageClipComplexByType(C64,min,max);
+
+    //  6. Call psImageClipComplexRegion with NULL input parameter; should error
+    //     but not stop execution.
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(NULL,0,0,0,0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+
+    img = psImageAlloc(c,r,PS_TYPE_C32);
+    for (unsigned row=0;row<r;row++) {
+        psC32* imgRow = img->data.C32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = row+I*col;
+        }
+    }
+
+    //  7. Call psImageClipComplexRegion with min > max; should error and return 0,
+    //     but not stop execution
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,10.0+I*1.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for creal(min)>creal(max).");
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,1.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for cimag(min)>cimag(max).");
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,10.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for min>max.");
+        return 3;
+    }
+
+    //  8. Call psImageClipComplexRegion with the follow vmin/vmax values; each
+    //     should error and return 0, but not stop execution
+    //      a) vmin < datatype region's minimum
+    //      b) vmax < datatype region's minimum
+    //      c) vmin > datatype region's maximum
+    //      d) vmax > datatype region's maximum
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      -2.0*(double)FLT_MAX,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmin not in datatype range.");
+        return 80;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      2.0*(double)FLT_MAX,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmin not in datatype range.");
+        return 81;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      -2.0*(double)FLT_MAX*I,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmin not in datatype range.");
+        return 82;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      2.0*(double)FLT_MAX*I,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmin not in datatype range.");
+        return 83;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      -2.0*(double)FLT_MAX);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmax not in datatype range.");
+        return 84;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      2.0*(double)FLT_MAX);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmax not in datatype range.");
+        return 85;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      -2.0*(double)FLT_MAX*I);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmax not in datatype range.");
+        return 87;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      2.0*(double)FLT_MAX*I);
+    if (retVal != 0) {
+        psError(__func__,"Expected zero return for vmax not in datatype range.");
+        return 88;
+    }
+
+
+    // now check if vmin > vmax is OK
+    for (unsigned row=0;row<r;row++) {
+        psC32* imgRow = img->data.C32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = row+I*col;
+        }
+    }
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      10.0,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal == 0) {
+        psError(__func__,"Didn't expect zero return for vmin > vmax.");
+        return 83;
+    }
+
+
+    psFree(img);
+    img = NULL;
+
+    //  9. Call psImageClipComplexRegion with the max value out of datatype's
+    //     range; should clip as expected (see step 1-5). Repeat with min value
+    //     out of datatype's range.
+
+    testImageClipComplexByType(C32,-(double)FLT_MAX*2.0-I*(double)FLT_MAX*2.0,10.0+I*10.0);
+    testImageClipComplexByType(C32,10.0+I*10.0,(double)FLT_MAX*2.0+I*(double)FLT_MAX*2.0);
+
+    return 0;
+}
+
+int testImageOverlay(void)
+{
+
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    unsigned int c = 128;
+    unsigned int r = 256;
+    int retVal;
+
+    /*
+    psImageSectionOverlay shall modified pixel values in a psImage structure to
+    be equal to the value of the originaldata and an overlay image with a
+    specified operation. Valid operations include =, +, -, *, /.
+
+    Verify the returned integer is zero
+    and the input parameter psImage structure is modified at the specified
+    location and range with the given overlay image and the specified
+    function. Cases should include all the valid operations. Comparison of
+    expected values should include a delta to allow for testing on
+    different platforms.
+
+    */
+
+
+
+    #define testOverlayTypeOP(DATATYPE,OP,OPSTRING) \
+    img = psImageAlloc(c,r,PS_TYPE_##DATATYPE); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = 6.0; \
+        } \
+    } \
+    img2 = psImageAlloc(c/2,r/2,PS_TYPE_##DATATYPE); \
+    for (unsigned row=0;row<r/2;row++) { \
+        ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c/2;col++) { \
+            img2Row[col] = 2.0; \
+        } \
+    } \
+    retVal = psImageOverlaySection(img,img2,c/4,r/4,OPSTRING); \
+    if (retVal != 0) { \
+        psError(__func__,"psImageOverlaySection returned non-zero %s op",OPSTRING); \
+        return 1; \
+    } \
+    for (unsigned row=0;row<r;row++) { \
+        ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+        ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##DATATYPE val = 6.0; \
+            if ( ! (row < r/4 || row >= r/2+r/4 || col < c/4 || col >= c/2+c/4)) { \
+                val OP 2.0; \
+            } \
+            if (fabsf(imgRow[col] - val) > FLT_EPSILON) { \
+                psError(__func__,"Value incorrect at %d,%d (%.2f vs %.2f for %s)", \
+                        col,row,imgRow[col],val,OPSTRING); \
+                return 2; \
+            } \
+            if (row < r/2 && col < c/2 && fabsf(img2Row[col] - 2.0) > FLT_EPSILON) { \
+                psError(__func__,"Overlay modified at %d,%d (%.2f for %s)", \
+                        col,row,img2Row[col],OPSTRING); \
+                return 2; \
+            } \
+        } \
+    } \
+    psFree(img); \
+    psFree(img2);
+
+    #define testOverlayType(DATATYPE) \
+    testOverlayTypeOP(DATATYPE,+=,"+"); \
+    testOverlayTypeOP(DATATYPE,-=,"-"); \
+    testOverlayTypeOP(DATATYPE,*=,"*");\
+    testOverlayTypeOP(DATATYPE,/=,"/");\
+    testOverlayTypeOP(DATATYPE,=,"=");
+
+    testOverlayType(C64);
+    testOverlayType(C32);
+    testOverlayType(F64);
+    testOverlayType(F32);
+    testOverlayType(S16);
+    testOverlayType(S8);
+    testOverlayType(U16);
+    testOverlayType(U8);
+
+    /*
+    Verify the returned integer is equal to non-zero and the input psImage structure
+    is unmodified, if the overlay specified is not within the data range of the
+    input psImage structure.
+    */
+
+    img = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = 6.0f;
+        }
+    }
+    img2 = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 2.0f;
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as overlay isn't "
+             "within image boundaries");
+    retVal = psImageOverlaySection(img,img2,c/4,r/4,"+");
+    if (retVal == 0) {
+        psError(__func__,"psImageOverlaySection returned zero even though "
+                "overlay too big");
+        return 3;
+    }
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            if (imgRow[col] != 6.0f) {
+                psError(__func__,"Input image modified when overlay size too big");
+                return 4;
+            }
+        }
+    }
+
+    /*
+    Verify the returned integer is equal to non-zero, the input psImage
+    structure is unmodified and program execution doesn't stop, if the
+    overlay specified is null.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as overlay is NULL");
+    retVal = psImageOverlaySection(img,NULL,c/4,r/4,"+");
+    if (retVal == 0) {
+        psError(__func__,"psImageOverlaySection returned zero even though "
+                "overlay too big");
+        return 5;
+    }
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            if (imgRow[col] != 6.0f) {
+                psError(__func__,"Input image modified when overlay NULL");
+                return 6;
+            }
+        }
+    }
+
+    /*
+    Verify the returned integer is equal to non-zero and program execution
+    doesn't stop, if the input parameter image is null.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as image input is NULL");
+    retVal = psImageOverlaySection(NULL,img2,c/4,r/4,"+");
+    if (retVal == 0) {
+        psError(__func__,"psImageOverlaySection returned zero even though "
+                "overlay too big");
+        return 7;
+    }
+
+    /*
+    Verify program execution doen't stop, if the overly image contains
+    zero values with division operation is specified.
+    */
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 0.0f;
+        }
+    }
+    retVal = psImageOverlaySection(img,img2,0,0,"/");
+    if (retVal != 0) {
+        psError(__func__,"psImageOverlaySection returned non-zero when "
+                "checking divide-by-zero.");
+        return 8;
+    }
+
+    psFree(img);
+    psFree(img2);
+
+    return 0;
+}
+
+static int testImageRebin(void)
+{
+
+    /*
+    This function shall generate a rescaled version of a psImage structure 
+    derived from a specified statistics method.
+    */
+
+    psImage* in = NULL;
+    psImage* out = NULL;
+    psImage* out2 = NULL;
+    psImage* meanTruth = NULL;
+    psImage* maxTruth = NULL;
+    psStats stats;
+
+    /*
+    Verify the returned psImage structure contains expected values, if the 
+    input parameter input contains known data, the input scale is a known 
+    value with a known statistical method specified in stats. Cases should 
+    include at least two different scales and statistical methods. Comparison 
+    of expected values should include a delta to allow testing on different 
+    platforms.
+    */
+
+    in = psImageAlloc(16,16,PS_TYPE_F32);
+    meanTruth = psImageAlloc(4,4,PS_TYPE_F32);
+    maxTruth = psImageAlloc(6,6,PS_TYPE_F32);
+    memset(meanTruth->data.F32[0],0,sizeof(psF32)*4*4);
+    memset(maxTruth->data.F32[0],0,sizeof(psF32)*6*6);
+
+    for (int row = 0; row<16; row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* meanTruthRow = meanTruth->data.F32[row/4];
+        psF32* maxTruthRow = maxTruth->data.F32[row/3];
+        for (int col = 0; col<16; col++) {
+            inRow[col] = row + col;
+            meanTruthRow[col/4] += row + col;
+            if (maxTruthRow[col/3] < row + col) {
+                maxTruthRow[col/3] = row+col;
+            }
+        }
+    }
+    for (int row = 0; row<4; row++) {
+        psF32* meanTruthRow = meanTruth->data.F32[row];
+        for (int col = 0; col<4; col++) {
+            meanTruthRow[col] /= 16;
+        }
+    }
+
+    stats.options = PS_STAT_SAMPLE_MEAN;
+    out = psImageRebin(NULL,in,4,&stats);
+
+    if (out == NULL) {
+        psError(__func__,"psImageRebin returned a NULL pointer!?");
+        return 1;
+    }
+
+    if (out->numRows != 4 || out->numCols != 4) {
+        psError(__func__,"psImageRebin didn't produce the proper size image "
+                "(%d x %d).",
+                out->numCols, out->numRows);
+        return 2;
+    }
+
+    for (int row = 0; row<4; row++) {
+        psF32* outRow = out->data.F32[row];
+        psF32* truthRow = meanTruth->data.F32[row];
+        for (int col = 0; col<4; col++) {
+            if (fabsf(outRow[col]-truthRow[col]) > FLT_EPSILON) {
+                psError(__func__,"psImageRebin didn't produce the proper "
+                        "result at (%d,%d) [%f vs %f].",
+                        col,row,outRow[col],truthRow[col]);
+                return 3;
+            }
+        }
+    }
+
+    stats.options = PS_STAT_MAX;
+    out2 = psImageRebin(out,in,3,&stats);
+
+    // Verify the returned psImage structure is equal to the input parameter
+    // out if specified.
+    if (out != out2) {
+        psError(__func__,"psImageRebin didn't recycle a psImage properly!?");
+        return 7;
+    }
+
+    if (out == NULL) {
+        psError(__func__,"psImageRebin returned a NULL pointer!?");
+        return 4;
+    }
+
+    if (out->numRows != 6 || out->numCols != 6) {
+        psError(__func__,"psImageRebin didn't produce the proper size image "
+                "(%d x %d).",
+                out->numCols, out->numRows);
+        return 5;
+    }
+
+    for (int row = 0; row<6; row++) {
+        psF32* outRow = out->data.F32[row];
+        psF32* truthRow = maxTruth->data.F32[row];
+        for (int col = 0; col<6; col++) {
+            if (fabsf(outRow[col]-truthRow[col]) > FLT_EPSILON) {
+                psError(__func__,"psImageRebin didn't produce the proper "
+                        "result at (%d,%d) [%f vs %f].",
+                        col,row,outRow[col],truthRow[col]);
+                return 6;
+            }
+        }
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter input is null.
+
+    out2 = psImageRebin(NULL,NULL,1,&stats);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the input was "
+                "NULL!?");
+        return 8;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter scale is less than or equal to zero.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    out2 = psImageRebin(NULL,in,0,&stats);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the scale was "
+                "zero!?");
+        return 9;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter stats is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    out2 = psImageRebin(NULL,in,1,NULL);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the stats was "
+                "NULL!?");
+        return 10;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter psStats structure member options
+    // is zero or any value which doesn't correspond to a valid statistical
+    // method.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    stats.options = 0;
+    out2 = psImageRebin(NULL,in,1,&stats);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the stats "
+                "options was zero!?");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    stats.options = PS_STAT_USE_RANGE;
+    out2 = psImageRebin(NULL,in,1,&stats);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the stats "
+                "options was PS_STAT_USE_RANGE!?");
+        return 12;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter psStats structure member options
+    // specifies more than one valid statistical method.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    stats.options = PS_STAT_SAMPLE_MEAN + PS_STAT_MAX;
+    out2 = psImageRebin(NULL,in,1,&stats);
+
+    if (out2 != NULL) {
+        psError(__func__,"psImageRebin returned an image though the stats "
+                "options was PS_STAT_SAMPLE_MEAN+PS_STAT_MAX!?");
+        return 13;
+    }
+
+
+    psFree(in);
+    psFree(out);
+    psFree(meanTruth);
+    psFree(maxTruth);
+
+    return 0;
+}
+
+static int testImageRoll(void)
+{
+
+    psImage* in;
+    psImage* out;
+    psImage* out2;
+    int rows = 64;
+    int cols = 64;
+
+
+    /*
+     The function psImageRoll shall generate a new psImage structure by 
+     rolling the input image the correponding number of pixels in the vertical
+     and/or horizontal direction. The image output image shall be the same size
+     as the input image. Values which roll off the image are wrapped to the 
+     other side.
+
+     Verify the returned psImage structure contains expected values, if the 
+     input image contains known values and the roll performed is known. 
+     Cases should include no roll, vertical roll, horizontal roll and 
+     combination vertical/horizontal rolls. Positive and negative rolls 
+     should be performed.
+    */
+
+    in = psImageAlloc(cols,rows,PS_TYPE_F32);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            inRow[col] = (psF32)row+(psF32)col/1000.0f;
+        }
+    }
+
+    out = psImageRoll(NULL,in,0,0);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=0.",
+                        col,row,inRow[col],outRow[col]);
+                return 3;
+            }
+        }
+    }
+
+    out2 = psImageRoll(out,in,cols/4,0);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=0.",
+                        col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                return 4;
+            }
+        }
+    }
+
+    // Verify the returned psImage structure pointer is equal to the input
+    // parameter out if provided.
+    if (out2 != out) {
+        psError(__func__,"psImageRoll didn't recycle my out psImage!?");
+        return 1;
+    }
+
+    out = psImageRoll(out,in,0,rows/4);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=rows/4.",
+                        col,row,inRow[col],outRow[col]);
+                return 5;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,cols/4,rows/4);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4.",
+                        col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                return 6;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,-cols/4,0);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[(col+(cols-cols/4)) % cols] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=-cols/4, dy=0.",
+                        col,row,inRow[(col+(cols-cols/4)) % cols],outRow[col]);
+                return 7;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,0,-rows/4);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows-rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=-rows/4.",
+                        col,row,inRow[col],outRow[col]);
+                return 8;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,-cols/4,-rows/4);
+    for (int row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows-rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (int col=0;col<cols;col++) {
+            if (inRow[(col+cols-cols/4) % cols] != outRow[col]) {
+                psError(__func__,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4.",
+                        col,row,inRow[(col+cols-cols/4) % cols],outRow[col]);
+                return 9;
+            }
+        }
+    }
+
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error.");
+    out2 = psImageRoll(NULL,NULL,0,0);
+    if (out2 != NULL) {
+        psError(__func__,"psImageRoll did not return NULL though input image was NULL!?");
+        return 2;
+    }
+
+    psFree(in);
+    psFree(out);
+
+    return 0;
+}
+
+int testImageRotate(void)
+{
+    /*
+
+    This function shall calculate a new psImage structure based upon the 
+    rotation of a given psImage structure. The center of rotation shall be the 
+    center pixel of the input image.
+
+    The following steps of the testpoint are done manually via inspection of 
+    temp/fOut.fits & temp/sOut.fits.
+
+        * Verify the returned psImage structure contains expected values, if 
+          the input parameter psImage contains known values. Cases should 
+          include rotations of 0, 60, 90, 120, 180, 240, 360 and at leat one 
+          other arbitrary angle. Cases of the input image should include image
+          with a center pixel and an image without a center pixel.
+        * Verify the returned psImage structure contains pixels set to TBD, if
+          the rotation and input psImage to not correspond to the output image.
+
+    */
+
+    psImage* fOut = NULL;
+    psImage* sOut = NULL;
+    psImage* fTruth = NULL;
+    psImage* sTruth = NULL;
+    int rows = 64;
+    int cols = 64;
+    psImage* fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage* sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+
+    for(int row=0;row<rows;row++) {
+        psF32* fRow = fImg->data.F32[row];
+        psS16* sRow = sImg->data.S16[row];
+        for (int col=0;col<cols;col++) {
+            fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+            sRow[col] = row-2*col;
+        }
+    }
+
+    // since interpolation is involved, etc., the simplist way to verify things
+    // is to verify the results manually and bless it for automated comparison
+    // thereafter
+
+
+    // write results of various rotates to a file and verify with truth images
+    mkdir("temp",0777);
+    remove
+        ("temp/fOut.fits")
+        ;
+    remove
+        ("temp/sOut.fits")
+        ;
+    int index = 0;
+    bool fail = false;
+    for (int rot=-180;rot<=180;rot+=45) {
+        psImage* oldOut = fOut;
+        fOut = psImageRotate(fOut,fImg,rot,-1.0,PS_INTERPOLATE_FLAT);
+        // Verify the returned psImage structure is equal to the input
+        // parameter out if provided.
+        if (oldOut != NULL && oldOut != fOut) {
+            psError(__func__,"the output recycle functionality failed");
+            return 2;
+        }
+        sOut = psImageRotate(sOut,sImg,rot,-1.0,PS_INTERPOLATE_FLAT);
+        if (! psImageWriteSection(fOut,0,0,0,NULL,index,"temp/fOut.fits") ) {
+            psError(__func__,"Can not write to temp/fOut.fits, so why continue!?");
+            return 20;
+        }
+        if (! psImageWriteSection(sOut,0,0,0,NULL,index,"temp/sOut.fits") ) {
+            psError(__func__,"Can not write to temp/sOut.fits, so why continue!?");
+            return 21;
+        }
+
+        // now, let's compare this with the verified file
+        fTruth = psImageReadSection(fTruth,0,0,0,0,0,NULL,index,"verified/fOut.fits");
+        sTruth = psImageReadSection(sTruth,0,0,0,0,0,NULL,index,"verified/sOut.fits");
+
+        if (fTruth == NULL) {
+            psError(__func__,"verified psF32 image failed to be read (%d deg. rotation)",
+                    rot);
+            fail = true;
+        } else {
+            if (fTruth->numRows != fOut->numRows || fTruth->numCols != fOut->numCols) {
+                psError(__func__,"Rotated float image size did not match truth "
+                        "image for %d deg rotation (%dx%d vs %dx%d).",
+                        rot,fOut->numCols,fOut->numRows,fTruth->numCols,fTruth->numRows);
+                fail = true;
+            } else {
+                for (int row=0;row<fTruth->numRows;row++) {
+                    psF32* truthRow = fTruth->data.F32[row];
+                    psF32* outRow = fOut->data.F32[row];
+                    for (int col=0;col<fTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(__func__,"Float Image mismatch (%f vs %f) at %d,%d.",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sTruth == NULL) {
+            psError(__func__,"verified psS16 image failed to be read "
+                    "(%d deg. rotation)",rot);
+            fail = true;
+        } else {
+            if (sTruth->numRows != sOut->numRows ||
+                    sTruth->numCols != sOut->numCols) {
+                psError(__func__,"Rotated short image size did not match truth "
+                        "image for %d deg rotation.",rot);
+                fail = true;
+            } else {
+                for (int row=0;row<sTruth->numRows;row++) {
+                    psS16* truthRow = sTruth->data.S16[row];
+                    psS16* outRow = sOut->data.S16[row];
+                    for (int col=0;col<sTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(__func__,"Short Image mismatch (%d vs %d) "
+                                    "at %d,%d.",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+
+        index++;
+    }
+
+    if (fail) {
+        psError(__func__,"One or more images didn't match truth or truth did "
+                "not exist.");
+        return 10;
+    }
+
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if the input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    fOut = psImageRotate(fOut,NULL,0,0,PS_INTERPOLATE_FLAT);
+    if (fOut != NULL) {
+        psError(__func__,"NULL wasn't returned though the input image was NULL.");
+        return 3;
+    }
+
+    psFree(sOut);
+    psFree(fImg);
+    psFree(sImg);
+    psFree(fTruth);
+    psFree(sTruth);
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageStats00.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageStats00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageStats00.c	(revision 1553)
@@ -0,0 +1,183 @@
+/*****************************************************************************
+   This routine must ensure that the psHistogram structure is correctly
+   allocated and populated by the psImageHistogram() function.
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psImage.h"
+#include "psImageStats.h"
+#define NUM_BINS 20
+#define IMAGE_SIZE 20
+#define N 32
+#define M 64
+
+int main()
+{
+    psHistogram * myHist = NULL;
+    psHistogram *myHist2 = NULL;
+    psImage *tmpImage = NULL;
+    psImage *tmpMask = NULL;
+    int testStatus = true;
+    int memLeaks = 0;
+    int nb = 0;
+    int i = 0;
+    int j = 0;
+    int IMAGE_X_SIZE = 0;
+    int IMAGE_Y_SIZE = 0;
+    int currentId = 0;
+
+    currentId = psMemGetId();
+    for ( nb = 0;nb < 6;nb++ ) {
+        if ( nb == 0 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 1 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 2 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 3 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 4 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = M;
+        }
+        if ( nb == 5 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        printf( "*******************************\n" );
+        printf( "* IMAGE SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        printf( "*******************************\n" );
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                      */
+        /*********************************************************************/
+        tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+
+        for ( i = 0;i < tmpImage->numRows;i++ ) {
+            for ( j = 0;j < tmpImage->numCols;j++ ) {
+                tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j + 0.1 );
+            }
+        }
+        tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+        for ( i = 0;i < tmpMask->numRows;i++ ) {
+            for ( j = 0;j < tmpMask->numCols;j++ ) {
+                if ( ( i > ( tmpMask->numRows / 2 ) ) &&
+                        ( j > ( tmpMask->numCols / 2 ) ) ) {
+                    tmpMask->data.U8[ i ][ j ] = 1;
+                } else {
+                    tmpMask->data.U8[ i ][ j ] = 0;
+                }
+            }
+        }
+
+        /*************************************************************************/
+        /*  Calculate Histogram with no mask                             */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Calculate Histogram, no mask" );
+
+        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                                   NUM_BINS );
+        myHist = psImageHistogram( myHist, tmpImage, NULL, 0 );
+        for ( i = 0;i < NUM_BINS;i++ ) {
+            printf( "Bin number %d bounds: (%.1f - %.1f) data (%d)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.S32[ i ] );
+        }
+        psFree( myHist );
+
+        psMemCheckCorruption( 1 );
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Calculate Histogram, no mask",
+                     testStatus );
+
+        /*************************************************************************/
+        /*  Calculate Histogram with mask                                */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Calculate Histogram with mask" );
+
+        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                                   NUM_BINS );
+        myHist = psImageHistogram( myHist, tmpImage, tmpMask, 1 );
+        for ( i = 0;i < NUM_BINS;i++ ) {
+            printf( "Bin number %d bounds: (%.2f - %.2f) data (%d)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.S32[ i ] );
+        }
+
+        psMemCheckCorruption( 1 );
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Calculate Histogram with mask",
+                     testStatus );
+
+        /*************************************************************************/
+        /*  Deallocate data structures                                   */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Deallocate the psHistogram/psImage structure." );
+        psFree( myHist );
+        psFree( tmpImage );
+        psFree( tmpMask );
+
+        psMemCheckCorruption( 1 );
+        memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+        if ( 0 != memLeaks ) {
+            psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+        }
+
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Deallocate the psHistogram/psImage structure.",
+                     testStatus );
+    }
+    printPositiveTestHeader( stdout,
+                             "psImageStats functions",
+                             "Calling psImageHistogram() with NULL parameters" );
+
+    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+    myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                               NUM_BINS );
+    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        printf( "ERROR: myHist2 not equal to NULL\n" );
+    }
+
+    myHist2 = psImageHistogram( myHist, NULL, NULL, 0 );
+    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        printf( "ERROR: myHist2 not equal to NULL\n" );
+    }
+
+    psMemCheckCorruption( 1 );
+    psFree( myHist );
+    psFree( tmpImage );
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+    if ( 0 != memLeaks ) {
+        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+    }
+
+    printFooter( stdout,
+                 "psImageStats functions",
+                 "Calling psImageHistogram() with NULL parameters",
+                 testStatus );
+
+    return ( !testStatus );
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageStats01.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageStats01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageStats01.c	(revision 1553)
@@ -0,0 +1,179 @@
+/*****************************************************************************
+   This routine must ensure that the psImageStats() routine can correctly
+   call the psVectorStats() routine.  Since the psVectorStats() will be
+   thouroughly tested elsewhere, we will only test psImageStats() with
+   the PS_STAT_SAMPLE_MEAN here.
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psImage.h"
+#include "psImageStats.h"
+#define NUM_BINS 20
+#define N 32
+#define M 64
+
+int main()
+{
+    psStats * myStats = NULL;
+    psStats *myStats2 = NULL;
+    psImage *tmpImage = NULL;
+    psImage *tmpMask = NULL;
+    int testStatus = true;
+    int memLeaks = 0;
+    int nb = 0;
+    int i = 0;
+    int j = 0;
+    int IMAGE_X_SIZE = 0;
+    int IMAGE_Y_SIZE = 0;
+    int currentId = 0;
+
+    currentId = psMemGetId();
+    for ( nb = 0;nb < 6;nb++ ) {
+        if ( nb == 0 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 1 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 2 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 3 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 4 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = M;
+        }
+        if ( nb == 5 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        printf( "*******************************\n" );
+        printf( "* IMAGE SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        printf( "*******************************\n" );
+
+        /*************************************************************************/
+        /*  Allocate and initialize data structures                      */
+        /*************************************************************************/
+        tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+
+        for ( i = 0;i < tmpImage->numRows;i++ ) {
+            for ( j = 0;j < tmpImage->numCols;j++ ) {
+                tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j );
+            }
+        }
+        tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+        for ( i = 0;i < tmpMask->numRows;i++ ) {
+            for ( j = 0;j < tmpMask->numCols;j++ ) {
+                if ( ( i > ( tmpMask->numRows / 2 ) ) &&
+                        ( j > ( tmpMask->numCols / 2 ) ) ) {
+                    tmpMask->data.U8[ i ][ j ] = 1;
+                } else {
+                    tmpMask->data.U8[ i ][ j ] = 0;
+                }
+            }
+        }
+
+        myStats = psStatsAlloc( PS_STAT_SAMPLE_MEAN );
+        /*************************************************************************/
+        /*  Calculate Sample Mean with no mask                           */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Calculate Sample Mean, no mask %d" );
+
+        myStats = psImageStats( myStats, tmpImage, NULL, 0 );
+        printf( "The sample mean was %.2f\n", myStats->sampleMean );
+
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Calculate Sample Mean, no mask",
+                     testStatus );
+
+        /*************************************************************************/
+        /*  Calculate Sample Mean with mask                              */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Calculate Sample Mean with mask" );
+
+        myStats = psImageStats( myStats, tmpImage, tmpMask, 1 );
+        printf( "The sample mean was %.2f\n", myStats->sampleMean );
+
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Calculate Sample Mean with mask",
+                     testStatus );
+
+        /*************************************************************************/
+        /*  Deallocate data structures                                   */
+        /*************************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psImageStats functions",
+                                 "Deallocate the psStats/psImage structure." );
+        psFree( myStats );
+        psFree( tmpImage );
+        psFree( tmpMask );
+
+        psMemCheckCorruption( 1 );
+        memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+        if ( 0 != memLeaks ) {
+            psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+        }
+
+        printFooter( stdout,
+                     "psImageStats functions",
+                     "Deallocate the psStats/psImage structure.",
+                     testStatus );
+    }
+
+    /*************************************************************************/
+    /*  Test With Various Null Inputs                                        */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psImageStats functions",
+                             "Test With Various Null Inputs" );
+
+    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+    myStats = psStatsAlloc( 0 );
+
+    myStats2 = psImageStats( myStats, NULL, NULL, 0 );
+    if ( myStats2 != NULL ) {
+        printf( "ERROR: myStats2 = psImageStats(myStats, NULL, NULL, 0) != NULL\n" );
+    }
+
+    myStats2 = psImageStats( NULL, tmpImage, NULL, 0 );
+    if ( myStats2 != NULL ) {
+        printf( "ERROR: myStats2 = psImageStats(NULL, tmpImage, NULL, 0) != NULL\n" );
+    }
+
+    myStats2 = psImageStats( myStats, tmpImage, NULL, 0 );
+
+    psFree( myStats );
+    psFree( tmpImage );
+    psFree( tmpMask );
+
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+    if ( 0 != memLeaks ) {
+        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+    }
+
+    printFooter( stdout,
+                 "psImageStats functions",
+                 "Test With Various Null Inputs",
+                 testStatus );
+    return ( !testStatus );
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageStats02.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageStats02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageStats02.c	(revision 1553)
@@ -0,0 +1,120 @@
+/*****************************************************************************
+   This routine must ensure that the psImageStats() routine can correctly
+   call the psVectorStats() routine.  Since the psVectorStats() will be
+   thouroughly tested elsewhere, we will only test psImageStats() with
+   the PS_STAT_SAMPLE_MEAN here.
+ 
+   NOTE: After you debug, set CHEBY_X_DIM != CHEBY_Y_DIM.
+   Also, uses non-square images.
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psImage.h"
+#include "psImageStats.h"
+#include <float.h>
+#include <math.h>
+#define IMAGE_SIZE 64
+#define CHEBY_X_DIM 8
+#define CHEBY_Y_DIM 8
+#define THRESHOLD 10
+int main()
+{
+    psStats * myStats = NULL;
+    psImage *tmpImage = NULL;
+    psImage *outImage = NULL;
+    psPolynomial2D *my2DPoly = NULL;
+    int testStatus = true;
+    int memLeaks = 0;
+    int i = 0;
+    int j = 0;
+    int currentId = 0;
+
+    currentId = psMemGetId();
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    tmpImage = psImageAlloc( IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32 );
+    outImage = psImageAlloc( IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32 );
+    for ( i = 0;i < IMAGE_SIZE;i++ ) {
+        for ( j = 0;j < IMAGE_SIZE;j++ ) {
+            tmpImage->data.F32[ i ][ j ] = 4.0;
+            tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j );
+            tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j ) + ( 4.0 * ( float ) i );
+            outImage->data.F32[ i ][ j ] = 0.0;
+        }
+    }
+    my2DPoly = psPolynomial2DAlloc( CHEBY_X_DIM, CHEBY_Y_DIM );
+    /*************************************************************************/
+    /*  Calculate Chebyshev Polynomials, no mask                     */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psImageStats functions",
+                             "Calculate Chebyshev Polynomials, no mask" );
+
+    my2DPoly = psImageFitPolynomial( tmpImage, my2DPoly );
+    for ( i = 0;i < CHEBY_X_DIM;i++ ) {
+        for ( j = 0;j < CHEBY_Y_DIM;j++ ) {
+            printf( "Cheby Polynomial (%d, %d) coefficient is %.2f\n", i, j, 0.0001f+my2DPoly->coeff[ i ][ j ] );
+        }
+    }
+
+    psMemCheckCorruption( 1 );
+    printFooter( stdout,
+                 "psImageStats functions",
+                 "Calculate Chebyshev Polynomials, no mask",
+                 testStatus );
+    /*************************************************************************/
+    /*  Evaluate Chebyshev Polynomials, no mask                      */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psImageStats functions",
+                             "Calculate Chebyshev Polynomials, no mask" );
+
+    outImage = psImageEvalPolynomial( outImage, my2DPoly );
+    for ( i = 0;i < IMAGE_SIZE;i++ ) {
+        for ( j = 0;j < IMAGE_SIZE;j++ ) {
+
+            //             printf("pixel[%d][%d] is (%f, %f)\n", i, j,
+            //                     tmpImage->data.F32[i][j],
+            //                     outImage->data.F32[i][j]);
+            if ( fabs( outImage->data.F32[ i ][ j ] - tmpImage->data.F32[ i ][ j ] ) > THRESHOLD ) {
+                printf( "Pixel (%d, %d) is %.2f, should be %.2f\n", i, j,
+                        outImage->data.F32[ i ][ j ],
+                        tmpImage->data.F32[ i ][ j ] );
+            }
+
+        }
+    }
+
+    psMemCheckCorruption( 1 );
+    printFooter( stdout,
+                 "psImageStats functions",
+                 "Calculate Chebyshev Polynomials, no mask",
+                 testStatus );
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psImageStats functions",
+                             "Deallocate the psStats/psImage structure." );
+    psFree( myStats );
+    psFree( tmpImage );
+    psFree( outImage );
+    psFree( my2DPoly );
+
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks( currentId, NULL, NULL );
+    if ( 0 != memLeaks ) {
+        psAbort( __func__, "Memory Leaks! (%d leaks)", memLeaks );
+    }
+
+    printFooter( stdout,
+                 "psImageStats functions",
+                 "Deallocate the psStats/psImage structure.",
+                 testStatus );
+
+    return ( !testStatus );
+}
Index: /tags/rel2_1/psLib/test/image/tst_psImageStats03.c
===================================================================
--- /tags/rel2_1/psLib/test/image/tst_psImageStats03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/tst_psImageStats03.c	(revision 1553)
@@ -0,0 +1,84 @@
+/*****************************************************************************
+    This routine must ensure that the psImagePixelInterpolation() routine
+    works correctly.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psImage.h"
+#include "psImageStats.h"
+#include <float.h>
+#include <math.h>
+#define IMAGE_SIZE 10
+
+int main()
+{
+    psImage *tmpImage   = NULL;
+    int testStatus      = true;
+    int memLeaks        = 0;
+    int i               = 0;
+    int j               = 0;
+    float pixel         = 0.0;
+    float x             = 0.0;
+    float y             = 0.0;
+    int currentId       = psMemGetId();
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psImageStats functions",
+                            "psImagePixelInterpolation()");
+
+    tmpImage = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32);
+    for (i=0;i<IMAGE_SIZE;i++) {
+        for (j=0;j<IMAGE_SIZE;j++) {
+            tmpImage->data.F32[i][j] = 4.0;
+            tmpImage->data.F32[i][j] = (float) (i + j) + (4.0 * (float) i);
+            tmpImage->data.F32[i][j] = (float) (i + j);
+            printf("%.1f ", tmpImage->data.F32[i][j]);
+        }
+        printf("\n");
+    }
+    for (i=0;i<IMAGE_SIZE-1;i++) {
+        for (j=0;j<IMAGE_SIZE-1;j++) {
+            x = 0.2 + (float) i;
+            y = 0.2 + (float) j;
+            pixel = psImagePixelInterpolate(tmpImage, x, y,0,PS_INTERPOLATE_BILINEAR);
+            printf("%.1f ", pixel);
+        }
+        printf("\n");
+    }
+
+    for (i=0;i<IMAGE_SIZE-1;i++) {
+        for (j=0;j<IMAGE_SIZE-1;j++) {
+            x = 0.2 + (float) i;
+            y = 0.2 + (float) j;
+            pixel = psImagePixelInterpolate(tmpImage, x, y,0,PS_INTERPOLATE_BILINEAR);
+            printf("image[%.1f][%.1f] is interpolated at %.1f\n", x, y, pixel);
+        }
+    }
+
+
+    psFree(tmpImage);
+    psMemCheckCorruption(1);
+    printFooter(stdout,
+                "psImageStats functions",
+                "psImagePixelInterpolation()",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    // GUS: replace with psFree()?
+    //    psImageFree(tmpImage);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (!testStatus);
+}
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImage.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImage.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImage.stderr	(revision 1553)
@@ -0,0 +1,101 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImage.c                                              *
+*            TestPoint: psImage{psImageAlloc}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I| testImageAlloc|#546 - psImageAlloc shall allocate memory for a psImage structure
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 101h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 102h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 104h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 108h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 301h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 302h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 304h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 308h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 404h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 408h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 808h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+<DATE><TIME>|<HOST>|I| testImageAlloc|Testing psImage with type 810h
+<DATE><TIME>|<HOST>|E|   psImageAlloc|Invalid value for number of rows or columns (numRows=0, numCols=0).
+
+---> TESTPOINT PASSED (psImage{psImageAlloc} | tst_psImage.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImage.c                                              *
+*            TestPoint: psImage{psImageSubset}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageSubset|memcpy(&preSubsetStruct,original,sizeof(psImage));
+<DATE><TIME>|<HOST>|I|testImageSubset|subset1 = psImageAlloc(c/4,r/4,PS_TYPE_U8);
+<DATE><TIME>|<HOST>|I|testImageSubset|subset2 = psImageSubset(subset1,original,c/2,r/2,c/4,r/4);
+<DATE><TIME>|<HOST>|I|testImageSubset|subset3 = psImageSubset(NULL,original,c/2,r/2,0,0);
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure is equal to the input psImage structure parameter out, if input parameter out is specified.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify a new psImage structure is created, if input parameter out is set to null.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure contains expected values in the row member, if the input psImage structure image contains known values.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure members nrow and ncol are equal to the input parameter nrow and ncol respectively.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure member type is equal to the input psImage structure member type.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure members row0 and col0 are equal to the input parameters row0 and col0 respectively.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure member parent is equal to the input psImage structure pointer image.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure member Nchildren is equal to zero.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure member children is null.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the input psImage structure image only has the following members changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure out at parent[Nchildren-1].
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure pointer is null and program execution doesn't stop, if the input parameter image is null. Also verified the input psImage structure is not modified.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because input image or its pixel buffer is NULL.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure pointer is null and program  execution doesn't stop, if the input parameters nrow and/or ncol are zero. Also verify input psImage structure is not modified.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because number of rows or columns are zero (64x0).
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because number of rows or columns are zero (0x128).
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure pointer is null and program execution doesn't stop, if the input parameters row0 and col0 are not within the range of values of psImage structure image.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because col0,row0 (128,0) is not a valid pixel location.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because col0,row0 (0,256) is not a valid pixel location.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because col0,row0 (-1,0) is not a valid pixel location.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image because col0,row0 (0,-1) is not a valid pixel location.
+<DATE><TIME>|<HOST>|I|testImageSubset|Verify the returned psImage structure pointer is null and program execution doesn't stop if the input parameters nrow, ncol, row0 and col0 specify a range of data not within the input psImage structure image.  Also verify the input psImage structure is not modified.
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image outside of image boundaries (size=128x256, subset=[64:<LINENO>,0:<LINENO>]).
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image outside of image boundaries (size=128x256, subset=[0:<LINENO>,128:<LINENO>]).
+<DATE><TIME>|<HOST>|I|testImageSubset|An error should follow...
+<DATE><TIME>|<HOST>|E|  psImageSubset|Can not subset image outside of image boundaries (size=128x256, subset=[64:<LINENO>,128:<LINENO>]).
+<DATE><TIME>|<HOST>|I|testImageSubset|psImageFreeChildren shall deallocate any children images of a psImage structure
+
+---> TESTPOINT PASSED (psImage{psImageSubset} | tst_psImage.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImage.c                                              *
+*            TestPoint: psImage{psImageCopy}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psU8
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psU16
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psU32
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psS8
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psS16
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psS32
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psF32
+<DATE><TIME>|<HOST>|I|  testImageCopy|Image Copy Test for psF64
+<DATE><TIME>|<HOST>|I|  testImageCopy|An error should follow...
+<DATE><TIME>|<HOST>|E|    psImageCopy|Can not copy image because input image or its pixel buffer is NULL.
+
+---> TESTPOINT PASSED (psImage{psImageCopy} | tst_psImage.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageExtraction.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageExtraction.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageExtraction.stderr	(revision 1553)
@@ -0,0 +1,27 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageExtraction.c                                    *
+*            TestPoint: psImage{psImageSlice}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|Input image can not be NULL.
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The stat options didn't specify a single supported statistic type.
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|Invalid direction flag (5)
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The specified region contains no data (0x0)
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The specified image region (2001,100 to 2001,100) is outside of image area (0,0 to 1999,999).
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The specified image region (200,1001 to 200,1001) is outside of image area (0,0 to 1999,999).
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The specified image region (200,100 to 2199,100) is outside of image area (0,0 to 1999,999).
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The specified image region (200,100 to 200,1099) is outside of image area (0,0 to 1999,999).
+<DATE><TIME>|<HOST>|I| testImageSlice|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageSlice|The stat options didn't specify a single supported statistic type.
+
+---> TESTPOINT PASSED (psImage{psImageSlice} | tst_psImageExtraction.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageFFT.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageFFT.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageFFT.stderr	(revision 1553)
@@ -0,0 +1,49 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageFFT.c                                           *
+*            TestPoint: psFFT{psImageFFT}                                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psImageFFT} | tst_psImageFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageFFT.c                                           *
+*            TestPoint: psFFT{psImageRealImaginary}                                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psImageRealImaginary} | tst_psImageFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageFFT.c                                           *
+*            TestPoint: psFFT{psImageComplex}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageComple|Following should be an error (type mismatch).
+<DATE><TIME>|<HOST>|E| psImageComplex|The inputs to psImageComplex must be the same type.
+<DATE><TIME>|<HOST>|I|testImageComple|Following should be an error (size mismatch).
+<DATE><TIME>|<HOST>|E| psImageComplex|The inputs to psImageComplex must be the same dimensions.
+
+---> TESTPOINT PASSED (psFFT{psImageComplex} | tst_psImageFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageFFT.c                                           *
+*            TestPoint: psFFT{psImageConjugate}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psImageConjugate} | tst_psImageFFT.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageFFT.c                                           *
+*            TestPoint: psFFT{psImagePowerSpectrum}                                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psFFT{psImagePowerSpectrum} | tst_psImageFFT.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageIO.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageIO.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageIO.stderr	(revision 1553)
@@ -0,0 +1,26 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageIO.c                                            *
+*            TestPoint: psImage{psImageReadSection}                                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+ <DATE> <TIME> |<HOST>|I|  testImageRead|Following should be an error as file doesn't exist.
+ <DATE> <TIME> |<HOST>|E|psImageReadSect|Could not open file 'foobar.fits'. (could not open the named file)
+ <DATE> <TIME> |<HOST>|I|  testImageRead|Following should be an error as filename is NULL.
+ <DATE> <TIME> |<HOST>|E|psImageReadSect|Must specify filename; it can not be NULL.
+ <DATE> <TIME> |<HOST>|I|  testImageRead|Following should be an error as extnum is invalid.
+ <DATE> <TIME> |<HOST>|E|psImageReadSect|Could not index to HDU #4 for file tmpImages/MxN_F32.fits. (tried to move past end of file)
+ <DATE> <TIME> |<HOST>|I|  testImageRead|Following should be an error as extname is invalid.
+ <DATE> <TIME> |<HOST>|E|psImageReadSect|Could not index to 'bogus' HDU for file tmpImages/MxN_F32.fits. (illegal HDU number)
+
+---> TESTPOINT PASSED (psImage{psImageReadSection} | tst_psImageIO.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageIO.c                                            *
+*            TestPoint: psImage{psImageWriteSection}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImage{psImageWriteSection} | tst_psImageIO.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageManip.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageManip.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageManip.stderr	(revision 1553)
@@ -0,0 +1,125 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageClip}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|  testImageClip|psImageClip shall limit the minimum and maximum data value within a psImage structure
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of F64 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of F32 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of S32 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of S16 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of S8 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of U32 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of U16 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of U8 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of C32 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Testing clipping of C64 imagery
+<DATE><TIME>|<HOST>|I|  testImageClip|Following should be an error (max<min)
+<DATE><TIME>|<HOST>|E|    psImageClip|psImageClip can not be invoked with max < min.
+
+---> TESTPOINT PASSED (psImage{psImageClip} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageClipNAN}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageClipNA|psImageClipNaN shall modified pixel values of NaN with a specified value
+
+---> TESTPOINT PASSED (psImage{psImageClipNAN} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageClipComplexRegion}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageClipCo|psImageClipNaN shall modified pixel values of NaN with a specified value
+<DATE><TIME>|<HOST>|I|testImageClipCo|Testing clipping at 409.6+256i to 682.667+512i for psC32
+<DATE><TIME>|<HOST>|I|testImageClipCo|Testing clipping at 409.6+256i to 682.667+512i for psC64
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Can not perform clip on NULL image
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|psImageClipComplexRegion can not be invoked with max < min in the real image space.
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|psImageClipComplexRegion can not be invoked with max < min in the imaginary image space.
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|psImageClipComplexRegion can not be invoked with max < min in the real image space.
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmin (-6.80565e+38+0i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmin (6.80565e+38+0i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmin (-0-6.80565e+38i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmin (0+6.80565e+38i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmax (-6.80565e+38+0i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmax (6.80565e+38+0i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmax (-0-6.80565e+38i) is outside of image's psC32 pixel range
+<DATE><TIME>|<HOST>|I|testImageClipCo|Following should be an error:
+<DATE><TIME>|<HOST>|E|psImageClipComp|Specified vmax (0+6.80565e+38i) is outside of image's psC32 pixel range
+
+---> TESTPOINT PASSED (psImage{psImageClipComplexRegion} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageOverlay}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageOverla|Following should error as overlay isn't within image boundaries
+<DATE><TIME>|<HOST>|E|psImageOverlayS|Overlay image (32,64 -> 159,319) is partially outside of the input image (128 x 256).
+<DATE><TIME>|<HOST>|I|testImageOverla|Following should error as overlay is NULL
+<DATE><TIME>|<HOST>|E|psImageOverlayS|one of the input images was NULL.
+<DATE><TIME>|<HOST>|I|testImageOverla|Following should error as image input is NULL
+<DATE><TIME>|<HOST>|E|psImageOverlayS|one of the input images was NULL.
+
+---> TESTPOINT PASSED (psImage{psImageOverlay} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageRebin}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|   psImageRebin|Input image is NULL.
+<DATE><TIME>|<HOST>|I| testImageRebin|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageRebin|The scale must be positive.
+<DATE><TIME>|<HOST>|I| testImageRebin|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageRebin|The stats input can not be NULL.
+<DATE><TIME>|<HOST>|I| testImageRebin|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageRebin|The stat options didn't specify a single supported statistic type.
+<DATE><TIME>|<HOST>|I| testImageRebin|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageRebin|The stat options didn't specify a single supported statistic type.
+<DATE><TIME>|<HOST>|I| testImageRebin|Following should be an error.
+<DATE><TIME>|<HOST>|E|   psImageRebin|The stat options didn't specify a single supported statistic type.
+
+---> TESTPOINT PASSED (psImage{psImageRebin} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageRoll}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|  testImageRoll|Following should generate an error.
+<DATE><TIME>|<HOST>|E|    psImageRoll|Input image can not be NULL.
+
+---> TESTPOINT PASSED (psImage{psImageRoll} | tst_psImageManip.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageManip.c                                         *
+*            TestPoint: psImage{psImageRotate}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|testImageRotate|Following should be an error
+<DATE><TIME>|<HOST>|E|  psImageRotate|The input image was NULL.
+
+---> TESTPOINT PASSED (psImage{psImageRotate} | tst_psImageManip.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageStats00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageStats00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageStats00.stdout	(revision 1553)
@@ -0,0 +1,429 @@
+*******************************
+* IMAGE SIZE is (1 by 1)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 0.1) data (1)
+Bin number 1 bounds: (0.1 - 0.2) data (0)
+Bin number 2 bounds: (0.2 - 0.3) data (0)
+Bin number 3 bounds: (0.3 - 0.4) data (0)
+Bin number 4 bounds: (0.4 - 0.5) data (0)
+Bin number 5 bounds: (0.5 - 0.6) data (0)
+Bin number 6 bounds: (0.6 - 0.7) data (0)
+Bin number 7 bounds: (0.7 - 0.8) data (0)
+Bin number 8 bounds: (0.8 - 0.9) data (0)
+Bin number 9 bounds: (0.9 - 1.0) data (0)
+Bin number 10 bounds: (1.0 - 1.1) data (0)
+Bin number 11 bounds: (1.1 - 1.2) data (0)
+Bin number 12 bounds: (1.2 - 1.3) data (0)
+Bin number 13 bounds: (1.3 - 1.4) data (0)
+Bin number 14 bounds: (1.4 - 1.5) data (0)
+Bin number 15 bounds: (1.5 - 1.6) data (0)
+Bin number 16 bounds: (1.6 - 1.7) data (0)
+Bin number 17 bounds: (1.7 - 1.8) data (0)
+Bin number 18 bounds: (1.8 - 1.9) data (0)
+Bin number 19 bounds: (1.9 - 2.0) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 0.10) data (1)
+Bin number 1 bounds: (0.10 - 0.20) data (0)
+Bin number 2 bounds: (0.20 - 0.30) data (0)
+Bin number 3 bounds: (0.30 - 0.40) data (0)
+Bin number 4 bounds: (0.40 - 0.50) data (0)
+Bin number 5 bounds: (0.50 - 0.60) data (0)
+Bin number 6 bounds: (0.60 - 0.70) data (0)
+Bin number 7 bounds: (0.70 - 0.80) data (0)
+Bin number 8 bounds: (0.80 - 0.90) data (0)
+Bin number 9 bounds: (0.90 - 1.00) data (0)
+Bin number 10 bounds: (1.00 - 1.10) data (0)
+Bin number 11 bounds: (1.10 - 1.20) data (0)
+Bin number 12 bounds: (1.20 - 1.30) data (0)
+Bin number 13 bounds: (1.30 - 1.40) data (0)
+Bin number 14 bounds: (1.40 - 1.50) data (0)
+Bin number 15 bounds: (1.50 - 1.60) data (0)
+Bin number 16 bounds: (1.60 - 1.70) data (0)
+Bin number 17 bounds: (1.70 - 1.80) data (0)
+Bin number 18 bounds: (1.80 - 1.90) data (0)
+Bin number 19 bounds: (1.90 - 2.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+*******************************
+* IMAGE SIZE is (1 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 1.7) data (2)
+Bin number 1 bounds: (1.7 - 3.3) data (2)
+Bin number 2 bounds: (3.3 - 5.0) data (1)
+Bin number 3 bounds: (5.0 - 6.6) data (2)
+Bin number 4 bounds: (6.6 - 8.2) data (2)
+Bin number 5 bounds: (8.2 - 9.9) data (1)
+Bin number 6 bounds: (9.9 - 11.6) data (2)
+Bin number 7 bounds: (11.6 - 13.2) data (2)
+Bin number 8 bounds: (13.2 - 14.9) data (1)
+Bin number 9 bounds: (14.9 - 16.5) data (2)
+Bin number 10 bounds: (16.5 - 18.2) data (2)
+Bin number 11 bounds: (18.2 - 19.8) data (1)
+Bin number 12 bounds: (19.8 - 21.5) data (2)
+Bin number 13 bounds: (21.5 - 23.1) data (2)
+Bin number 14 bounds: (23.1 - 24.8) data (1)
+Bin number 15 bounds: (24.8 - 26.4) data (2)
+Bin number 16 bounds: (26.4 - 28.1) data (1)
+Bin number 17 bounds: (28.1 - 29.7) data (2)
+Bin number 18 bounds: (29.7 - 31.4) data (2)
+Bin number 19 bounds: (31.4 - 33.0) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 1.65) data (2)
+Bin number 1 bounds: (1.65 - 3.30) data (2)
+Bin number 2 bounds: (3.30 - 4.95) data (1)
+Bin number 3 bounds: (4.95 - 6.60) data (2)
+Bin number 4 bounds: (6.60 - 8.25) data (2)
+Bin number 5 bounds: (8.25 - 9.90) data (1)
+Bin number 6 bounds: (9.90 - 11.55) data (2)
+Bin number 7 bounds: (11.55 - 13.20) data (2)
+Bin number 8 bounds: (13.20 - 14.85) data (1)
+Bin number 9 bounds: (14.85 - 16.50) data (2)
+Bin number 10 bounds: (16.50 - 18.15) data (2)
+Bin number 11 bounds: (18.15 - 19.80) data (1)
+Bin number 12 bounds: (19.80 - 21.45) data (2)
+Bin number 13 bounds: (21.45 - 23.10) data (2)
+Bin number 14 bounds: (23.10 - 24.75) data (1)
+Bin number 15 bounds: (24.75 - 26.40) data (2)
+Bin number 16 bounds: (26.40 - 28.05) data (1)
+Bin number 17 bounds: (28.05 - 29.70) data (2)
+Bin number 18 bounds: (29.70 - 31.35) data (2)
+Bin number 19 bounds: (31.35 - 33.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+*******************************
+* IMAGE SIZE is (32 by 1)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 1.7) data (2)
+Bin number 1 bounds: (1.7 - 3.3) data (2)
+Bin number 2 bounds: (3.3 - 5.0) data (1)
+Bin number 3 bounds: (5.0 - 6.6) data (2)
+Bin number 4 bounds: (6.6 - 8.2) data (2)
+Bin number 5 bounds: (8.2 - 9.9) data (1)
+Bin number 6 bounds: (9.9 - 11.6) data (2)
+Bin number 7 bounds: (11.6 - 13.2) data (2)
+Bin number 8 bounds: (13.2 - 14.9) data (1)
+Bin number 9 bounds: (14.9 - 16.5) data (2)
+Bin number 10 bounds: (16.5 - 18.2) data (2)
+Bin number 11 bounds: (18.2 - 19.8) data (1)
+Bin number 12 bounds: (19.8 - 21.5) data (2)
+Bin number 13 bounds: (21.5 - 23.1) data (2)
+Bin number 14 bounds: (23.1 - 24.8) data (1)
+Bin number 15 bounds: (24.8 - 26.4) data (2)
+Bin number 16 bounds: (26.4 - 28.1) data (1)
+Bin number 17 bounds: (28.1 - 29.7) data (2)
+Bin number 18 bounds: (29.7 - 31.4) data (2)
+Bin number 19 bounds: (31.4 - 33.0) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 1.65) data (2)
+Bin number 1 bounds: (1.65 - 3.30) data (2)
+Bin number 2 bounds: (3.30 - 4.95) data (1)
+Bin number 3 bounds: (4.95 - 6.60) data (2)
+Bin number 4 bounds: (6.60 - 8.25) data (2)
+Bin number 5 bounds: (8.25 - 9.90) data (1)
+Bin number 6 bounds: (9.90 - 11.55) data (2)
+Bin number 7 bounds: (11.55 - 13.20) data (2)
+Bin number 8 bounds: (13.20 - 14.85) data (1)
+Bin number 9 bounds: (14.85 - 16.50) data (2)
+Bin number 10 bounds: (16.50 - 18.15) data (2)
+Bin number 11 bounds: (18.15 - 19.80) data (1)
+Bin number 12 bounds: (19.80 - 21.45) data (2)
+Bin number 13 bounds: (21.45 - 23.10) data (2)
+Bin number 14 bounds: (23.10 - 24.75) data (1)
+Bin number 15 bounds: (24.75 - 26.40) data (2)
+Bin number 16 bounds: (26.40 - 28.05) data (1)
+Bin number 17 bounds: (28.05 - 29.70) data (2)
+Bin number 18 bounds: (29.70 - 31.35) data (2)
+Bin number 19 bounds: (31.35 - 33.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+*******************************
+* IMAGE SIZE is (32 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 3.2) data (10)
+Bin number 1 bounds: (3.2 - 6.4) data (18)
+Bin number 2 bounds: (6.4 - 9.6) data (27)
+Bin number 3 bounds: (9.6 - 12.8) data (36)
+Bin number 4 bounds: (12.8 - 16.0) data (45)
+Bin number 5 bounds: (16.0 - 19.2) data (74)
+Bin number 6 bounds: (19.2 - 22.4) data (66)
+Bin number 7 bounds: (22.4 - 25.6) data (75)
+Bin number 8 bounds: (25.6 - 28.8) data (84)
+Bin number 9 bounds: (28.8 - 32.0) data (93)
+Bin number 10 bounds: (32.0 - 35.2) data (118)
+Bin number 11 bounds: (35.2 - 38.4) data (78)
+Bin number 12 bounds: (38.4 - 41.6) data (69)
+Bin number 13 bounds: (41.6 - 44.8) data (60)
+Bin number 14 bounds: (44.8 - 48.0) data (51)
+Bin number 15 bounds: (48.0 - 51.2) data (54)
+Bin number 16 bounds: (51.2 - 54.4) data (30)
+Bin number 17 bounds: (54.4 - 57.6) data (21)
+Bin number 18 bounds: (57.6 - 60.8) data (12)
+Bin number 19 bounds: (60.8 - 64.0) data (3)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 3.20) data (10)
+Bin number 1 bounds: (3.20 - 6.40) data (18)
+Bin number 2 bounds: (6.40 - 9.60) data (27)
+Bin number 3 bounds: (9.60 - 12.80) data (36)
+Bin number 4 bounds: (12.80 - 16.00) data (45)
+Bin number 5 bounds: (16.00 - 19.20) data (74)
+Bin number 6 bounds: (19.20 - 22.40) data (66)
+Bin number 7 bounds: (22.40 - 25.60) data (75)
+Bin number 8 bounds: (25.60 - 28.80) data (84)
+Bin number 9 bounds: (28.80 - 32.00) data (93)
+Bin number 10 bounds: (32.00 - 35.20) data (115)
+Bin number 11 bounds: (35.20 - 38.40) data (66)
+Bin number 12 bounds: (38.40 - 41.60) data (48)
+Bin number 13 bounds: (41.60 - 44.80) data (30)
+Bin number 14 bounds: (44.80 - 48.00) data (12)
+Bin number 15 bounds: (48.00 - 51.20) data (0)
+Bin number 16 bounds: (51.20 - 54.40) data (0)
+Bin number 17 bounds: (54.40 - 57.60) data (0)
+Bin number 18 bounds: (57.60 - 60.80) data (0)
+Bin number 19 bounds: (60.80 - 64.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+*******************************
+* IMAGE SIZE is (32 by 64)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 4.8) data (15)
+Bin number 1 bounds: (4.8 - 9.6) data (40)
+Bin number 2 bounds: (9.6 - 14.4) data (65)
+Bin number 3 bounds: (14.4 - 19.2) data (90)
+Bin number 4 bounds: (19.2 - 24.0) data (90)
+Bin number 5 bounds: (24.0 - 28.8) data (135)
+Bin number 6 bounds: (28.8 - 33.6) data (157)
+Bin number 7 bounds: (33.6 - 38.4) data (160)
+Bin number 8 bounds: (38.4 - 43.2) data (160)
+Bin number 9 bounds: (43.2 - 48.0) data (128)
+Bin number 10 bounds: (48.0 - 52.8) data (160)
+Bin number 11 bounds: (52.8 - 57.6) data (160)
+Bin number 12 bounds: (57.6 - 62.4) data (160)
+Bin number 13 bounds: (62.4 - 67.2) data (150)
+Bin number 14 bounds: (67.2 - 72.0) data (102)
+Bin number 15 bounds: (72.0 - 76.8) data (105)
+Bin number 16 bounds: (76.8 - 81.6) data (80)
+Bin number 17 bounds: (81.6 - 86.4) data (55)
+Bin number 18 bounds: (86.4 - 91.2) data (30)
+Bin number 19 bounds: (91.2 - 96.0) data (6)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 4.80) data (15)
+Bin number 1 bounds: (4.80 - 9.60) data (40)
+Bin number 2 bounds: (9.60 - 14.40) data (65)
+Bin number 3 bounds: (14.40 - 19.20) data (90)
+Bin number 4 bounds: (19.20 - 24.00) data (90)
+Bin number 5 bounds: (24.00 - 28.80) data (135)
+Bin number 6 bounds: (28.80 - 33.60) data (157)
+Bin number 7 bounds: (33.60 - 38.40) data (160)
+Bin number 8 bounds: (38.40 - 43.20) data (160)
+Bin number 9 bounds: (43.20 - 48.00) data (128)
+Bin number 10 bounds: (48.00 - 52.80) data (154)
+Bin number 11 bounds: (52.80 - 57.60) data (130)
+Bin number 12 bounds: (57.60 - 62.40) data (105)
+Bin number 13 bounds: (62.40 - 67.20) data (76)
+Bin number 14 bounds: (67.20 - 72.00) data (42)
+Bin number 15 bounds: (72.00 - 76.80) data (30)
+Bin number 16 bounds: (76.80 - 81.60) data (6)
+Bin number 17 bounds: (81.60 - 86.40) data (0)
+Bin number 18 bounds: (86.40 - 91.20) data (0)
+Bin number 19 bounds: (91.20 - 96.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+*******************************
+* IMAGE SIZE is (64 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram, no mask}       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.0 - 4.8) data (15)
+Bin number 1 bounds: (4.8 - 9.6) data (40)
+Bin number 2 bounds: (9.6 - 14.4) data (65)
+Bin number 3 bounds: (14.4 - 19.2) data (90)
+Bin number 4 bounds: (19.2 - 24.0) data (90)
+Bin number 5 bounds: (24.0 - 28.8) data (135)
+Bin number 6 bounds: (28.8 - 33.6) data (157)
+Bin number 7 bounds: (33.6 - 38.4) data (160)
+Bin number 8 bounds: (38.4 - 43.2) data (160)
+Bin number 9 bounds: (43.2 - 48.0) data (128)
+Bin number 10 bounds: (48.0 - 52.8) data (160)
+Bin number 11 bounds: (52.8 - 57.6) data (160)
+Bin number 12 bounds: (57.6 - 62.4) data (160)
+Bin number 13 bounds: (62.4 - 67.2) data (150)
+Bin number 14 bounds: (67.2 - 72.0) data (102)
+Bin number 15 bounds: (72.0 - 76.8) data (105)
+Bin number 16 bounds: (76.8 - 81.6) data (80)
+Bin number 17 bounds: (81.6 - 86.4) data (55)
+Bin number 18 bounds: (86.4 - 91.2) data (30)
+Bin number 19 bounds: (91.2 - 96.0) data (6)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram, no mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calculate Histogram with mask}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Bin number 0 bounds: (0.00 - 4.80) data (15)
+Bin number 1 bounds: (4.80 - 9.60) data (40)
+Bin number 2 bounds: (9.60 - 14.40) data (65)
+Bin number 3 bounds: (14.40 - 19.20) data (90)
+Bin number 4 bounds: (19.20 - 24.00) data (90)
+Bin number 5 bounds: (24.00 - 28.80) data (135)
+Bin number 6 bounds: (28.80 - 33.60) data (157)
+Bin number 7 bounds: (33.60 - 38.40) data (160)
+Bin number 8 bounds: (38.40 - 43.20) data (160)
+Bin number 9 bounds: (43.20 - 48.00) data (128)
+Bin number 10 bounds: (48.00 - 52.80) data (154)
+Bin number 11 bounds: (52.80 - 57.60) data (130)
+Bin number 12 bounds: (57.60 - 62.40) data (105)
+Bin number 13 bounds: (62.40 - 67.20) data (76)
+Bin number 14 bounds: (67.20 - 72.00) data (42)
+Bin number 15 bounds: (72.00 - 76.80) data (30)
+Bin number 16 bounds: (76.80 - 81.60) data (6)
+Bin number 17 bounds: (81.60 - 86.40) data (0)
+Bin number 18 bounds: (86.40 - 91.20) data (0)
+Bin number 19 bounds: (91.20 - 96.00) data (0)
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Histogram with mask} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psHistogram/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psHistogram/psImage structure.} | tst_psImageStats00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats00.c                                       *
+*            TestPoint: psImageStats functions{Calling psImageHistogram() with NULL parameters} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Calling psImageHistogram() with NULL parameters} | tst_psImageStats00.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stderr	(revision 1553)
@@ -0,0 +1,3 @@
+<DATE><TIME>|<HOST>|E|   psImageStats|The input image can not be NULL.
+<DATE><TIME>|<HOST>|E|   psImageStats|The input psStats struct can not be NULL.
+<DATE><TIME>|<HOST>|E|   psImageStats|No statistic option/operation was specified.
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageStats01.stdout	(revision 1553)
@@ -0,0 +1,201 @@
+*******************************
+* IMAGE SIZE is (1 by 1)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 0.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 0.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+*******************************
+* IMAGE SIZE is (1 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 15.50
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 15.50
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+*******************************
+* IMAGE SIZE is (32 by 1)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 15.50
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 15.50
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+*******************************
+* IMAGE SIZE is (32 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 31.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 26.21
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+*******************************
+* IMAGE SIZE is (32 by 64)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 47.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 39.66
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+*******************************
+* IMAGE SIZE is (64 by 32)
+*******************************
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean, no mask %d}  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 47.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean, no mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Calculate Sample Mean with mask}    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+The sample mean was 39.66
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Sample Mean with mask} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats01.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats01.c                                       *
+*            TestPoint: psImageStats functions{Test With Various Null Inputs}      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Test With Various Null Inputs} | tst_psImageStats01.c)
+
Index: /tags/rel2_1/psLib/test/image/verified/tst_psImageStats02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/image/verified/tst_psImageStats02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/image/verified/tst_psImageStats02.stdout	(revision 1553)
@@ -0,0 +1,91 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats02.c                                       *
+*            TestPoint: psImageStats functions{Calculate Chebyshev Polynomials, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Cheby Polynomial (0, 0) coefficient is 189.00
+Cheby Polynomial (0, 1) coefficient is 25.94
+Cheby Polynomial (0, 2) coefficient is 0.00
+Cheby Polynomial (0, 3) coefficient is 2.88
+Cheby Polynomial (0, 4) coefficient is 0.00
+Cheby Polynomial (0, 5) coefficient is 1.04
+Cheby Polynomial (0, 6) coefficient is 0.00
+Cheby Polynomial (0, 7) coefficient is 0.53
+Cheby Polynomial (1, 0) coefficient is 129.68
+Cheby Polynomial (1, 1) coefficient is 0.00
+Cheby Polynomial (1, 2) coefficient is 0.00
+Cheby Polynomial (1, 3) coefficient is 0.00
+Cheby Polynomial (1, 4) coefficient is 0.00
+Cheby Polynomial (1, 5) coefficient is 0.00
+Cheby Polynomial (1, 6) coefficient is 0.00
+Cheby Polynomial (1, 7) coefficient is 0.00
+Cheby Polynomial (2, 0) coefficient is 0.00
+Cheby Polynomial (2, 1) coefficient is 0.00
+Cheby Polynomial (2, 2) coefficient is 0.00
+Cheby Polynomial (2, 3) coefficient is 0.00
+Cheby Polynomial (2, 4) coefficient is 0.00
+Cheby Polynomial (2, 5) coefficient is 0.00
+Cheby Polynomial (2, 6) coefficient is 0.00
+Cheby Polynomial (2, 7) coefficient is 0.00
+Cheby Polynomial (3, 0) coefficient is 14.40
+Cheby Polynomial (3, 1) coefficient is 0.00
+Cheby Polynomial (3, 2) coefficient is 0.00
+Cheby Polynomial (3, 3) coefficient is 0.00
+Cheby Polynomial (3, 4) coefficient is 0.00
+Cheby Polynomial (3, 5) coefficient is 0.00
+Cheby Polynomial (3, 6) coefficient is 0.00
+Cheby Polynomial (3, 7) coefficient is 0.00
+Cheby Polynomial (4, 0) coefficient is 0.00
+Cheby Polynomial (4, 1) coefficient is 0.00
+Cheby Polynomial (4, 2) coefficient is 0.00
+Cheby Polynomial (4, 3) coefficient is 0.00
+Cheby Polynomial (4, 4) coefficient is 0.00
+Cheby Polynomial (4, 5) coefficient is 0.00
+Cheby Polynomial (4, 6) coefficient is 0.00
+Cheby Polynomial (4, 7) coefficient is 0.00
+Cheby Polynomial (5, 0) coefficient is 5.17
+Cheby Polynomial (5, 1) coefficient is 0.00
+Cheby Polynomial (5, 2) coefficient is 0.00
+Cheby Polynomial (5, 3) coefficient is 0.00
+Cheby Polynomial (5, 4) coefficient is 0.00
+Cheby Polynomial (5, 5) coefficient is 0.00
+Cheby Polynomial (5, 6) coefficient is 0.00
+Cheby Polynomial (5, 7) coefficient is 0.00
+Cheby Polynomial (6, 0) coefficient is 0.00
+Cheby Polynomial (6, 1) coefficient is 0.00
+Cheby Polynomial (6, 2) coefficient is 0.00
+Cheby Polynomial (6, 3) coefficient is 0.00
+Cheby Polynomial (6, 4) coefficient is 0.00
+Cheby Polynomial (6, 5) coefficient is 0.00
+Cheby Polynomial (6, 6) coefficient is 0.00
+Cheby Polynomial (6, 7) coefficient is 0.00
+Cheby Polynomial (7, 0) coefficient is 2.63
+Cheby Polynomial (7, 1) coefficient is 0.00
+Cheby Polynomial (7, 2) coefficient is 0.00
+Cheby Polynomial (7, 3) coefficient is 0.00
+Cheby Polynomial (7, 4) coefficient is 0.00
+Cheby Polynomial (7, 5) coefficient is 0.00
+Cheby Polynomial (7, 6) coefficient is 0.00
+Cheby Polynomial (7, 7) coefficient is 0.00
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Chebyshev Polynomials, no mask} | tst_psImageStats02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats02.c                                       *
+*            TestPoint: psImageStats functions{Calculate Chebyshev Polynomials, no mask} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Calculate Chebyshev Polynomials, no mask} | tst_psImageStats02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psImageStats02.c                                       *
+*            TestPoint: psImageStats functions{Deallocate the psStats/psImage structure.} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psImageStats functions{Deallocate the psStats/psImage structure.} | tst_psImageStats02.c)
+
Index: /tags/rel2_1/psLib/test/psTest.c
===================================================================
--- /tags/rel2_1/psLib/test/psTest.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/psTest.c	(revision 1553)
@@ -0,0 +1,243 @@
+//
+// C Implementation: psTest
+//
+// Description:
+//
+//
+// Author: Robert DeSonia <robert.desonia@mhpcc.hpc.mil>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "psTest.h"
+#include "psMemory.h"
+#include "psError.h"
+
+#define HEADER_TOP    "/***************************** TESTPOINT ******************************************\\\n"
+#define HEADER_LINE_STRING   "* %20s: %-58s *\n"
+#define HEADER_LINE_INT      "* %20s: %-58d *\n"
+#define HEADER_BOTTOM "\\**********************************************************************************/\n\n"
+
+bool p_runTestSuite( FILE *fp, const char* testPointFile, const char* packageName,
+                     testDescription tests[], int argc, char * const argv[] )
+{
+    bool success = true;
+    bool runAll = true;
+    bool useFork = true;
+    bool found;
+    int c;
+    int n;
+    extern char *optarg;
+
+    if ( argc > 0 ) {
+        while ( ( c = getopt( argc, argv, "lhn:dt:" ) ) != -1 ) {
+            switch ( c ) {
+            case 'h':
+                printf( "Usage: %s [-l] [-d] [-h] [-n=Testpoint#] [-t=TestpointName]\n"
+                        "    where:\n"
+                        "           -l  : lists the testpoints contained in this test driver executable\n"
+                        "           -d  : turns on debugger-friendly mode (no forking, aborts/signals are not handled)\n"
+                        "           -h  : prints this help\n"
+                        "           -n  : specifies a particular testpoint by number to run\n"
+                        "           -t  : specifies a particular testpoint by name to run\n"
+                        "    (if no -l, -n or -t options are given, all testpoints are run)\n",
+                        argv[ 0 ] );
+                runAll = false;
+                break;
+            case 'd':
+                useFork = false;
+                break;
+            case 'l':
+                printf( "Test Driver:  %s\n", testPointFile );
+                printf( "Package Name: %s\n", packageName );
+                printf( "Testpoints:\n" );
+                runAll = false;
+                for ( int index = 0; tests[ index ].fcn != NULL; index++ ) {
+                    printf( "    %6d - %s \n", tests[ index ].testPointNumber,
+                            tests[ index ].testPointName );
+                }
+                printf( "\n" );
+                break;
+            case 't':
+                runAll = false;
+                for ( int index = 0; tests[ index ].fcn != NULL; index++ ) {
+                    if ( strcmp( optarg, tests[ index ].testPointName ) == 0 ) {
+                        success = p_runTest( fp,
+                                             testPointFile,
+                                             packageName,
+                                             tests[ index ].testPointName,
+                                             tests[ index ].fcn,
+                                             tests[ index ].expectedReturn,
+                                             useFork ) && success;
+                    }
+                }
+                break;
+            case 'n':
+                runAll = false;
+                if ( sscanf( optarg, "%i", &n ) != 1 ) {
+                    psError( __func__, "Failed to parse the testpoint number (%s).",
+                             optarg );
+                    break;
+                }
+                found = false;
+                for ( int index = 0; tests[ index ].fcn != NULL; index++ ) {
+                    if ( n == tests[ index ].testPointNumber ) {
+                        found = true;
+                        success = p_runTest( fp,
+                                             testPointFile,
+                                             packageName,
+                                             tests[ index ].testPointName,
+                                             tests[ index ].fcn,
+                                             tests[ index ].expectedReturn,
+                                             useFork ) && success;
+                    }
+                }
+                if ( ! found ) {
+                    psError( __func__, "The specified testpoint number (%d) doesn't exist in this test driver.",
+                             n );
+                    break;
+                }
+                break;
+            case '?':
+                psError( __func__, "Option %s is not recognized and is ignored.", optarg );
+                break;
+            }
+        }
+    }
+
+    if ( runAll ) {
+        for ( int index = 0; tests[ index ].fcn != NULL; index++ ) {
+            if ( ! tests[ index ].isDuplicateEntry ) {
+                success = p_runTest( fp,
+                                     testPointFile,
+                                     packageName,
+                                     tests[ index ].testPointName,
+                                     tests[ index ].fcn,
+                                     tests[ index ].expectedReturn,
+                                     useFork ) && success;
+            }
+        }
+    }
+
+    if ( ! success ) {
+        psError( testPointFile, "One or more tests failed" );
+    }
+
+    return success;
+}
+
+bool p_runTest( FILE *fp, const char* testPointFile, const char* packageName, const char* testPointName,
+                testFcn fcn, int expectedReturn, bool useFork )
+{
+    int childReturn = 0;
+    pid_t child;
+
+    p_printPositiveTestHeader( fp, testPointFile, packageName, testPointName );
+
+    if ( useFork ) {
+        child = fork();
+        if ( child == 0 ) {                   // I am the child process, run the test
+            int currentId = psMemGetId();
+            int retVal = fcn();
+            if ( retVal == 0 ) { // only bother checking memory if test executed to end.
+                if ( psMemCheckLeaks( currentId, NULL, stderr ) != 0 ) {
+                    psError( __func__, "Memory Leaks Detected" );
+                    retVal = 64;
+                }
+                psMemCheckCorruption( 1 );
+            }
+            exit( retVal );
+        } else
+            if ( child < 0 ) {
+                fprintf( fp, "Couldn't fork a process to run a negative test (%s|%s)",
+                         packageName, testPointName );
+                abort();
+            }
+
+        waitpid( child, &childReturn, 0 );
+        if ( WIFSIGNALED( childReturn ) ) {
+            childReturn = -WTERMSIG( childReturn );
+        } else {
+            childReturn = WEXITSTATUS( childReturn );
+        }
+    } else {
+        int currentId = psMemGetId();
+        childReturn = fcn();
+        if ( childReturn == 0 ) { // only bother checking memory if test executed to end.
+            if ( psMemCheckLeaks( currentId, NULL, stderr ) != 0 ) {
+                psError( __func__, "Memory Leaks Detected" );
+                childReturn = 64;
+            }
+            psMemCheckCorruption( 1 );
+        }
+    }
+
+
+    if ( childReturn != expectedReturn ) {
+        fprintf( fp, "Return value mismatch: expected %d, got %d",
+                 expectedReturn, childReturn );
+    }
+
+    p_printFooter( fp, testPointFile, packageName, testPointName,
+                   ( childReturn == expectedReturn ) );
+
+    return ( childReturn == expectedReturn );
+}
+
+void p_printPositiveTestHeader( FILE *fp,
+                                const char* testPointFile,
+                                const char* packageName,
+                                const char* testPointName )
+{
+    char TP[ 80 ];
+
+    snprintf( TP, 80, "%s{%s}", packageName, testPointName );
+
+    fprintf( fp, HEADER_TOP );
+    fprintf( fp, HEADER_LINE_STRING, "TestFile", testPointFile );
+    fprintf( fp, HEADER_LINE_STRING, "TestPoint", TP );
+    fprintf( fp, HEADER_LINE_STRING, "TestType", "Positive" );
+    fprintf( fp, HEADER_BOTTOM );
+}
+
+void p_printNegativeTestHeader( FILE *fp,
+                                const char* testPointFile,
+                                const char* packageName,
+                                const char* testPointName,
+                                const char* expectedError,
+                                int exitValue )
+{
+    char TP[ 80 ];
+
+    snprintf( TP, 80, "%s{%s}", packageName, testPointName );
+
+    fprintf( fp, HEADER_TOP );
+    fprintf( fp, HEADER_LINE_STRING, "TestFile", testPointFile );
+    fprintf( fp, HEADER_LINE_STRING, "TestPoint", TP );
+    fprintf( fp, HEADER_LINE_STRING, "TestType", "Negative" );
+    fprintf( fp, HEADER_LINE_STRING, "ExpectedErrorText", expectedError );
+    fprintf( fp, HEADER_LINE_INT, "ExpectedStatusValue", exitValue );
+    fprintf( fp, HEADER_BOTTOM );
+}
+
+
+void p_printFooter( FILE *fp,
+                    const char* testPointFile,
+                    const char* packageName,
+                    const char* testPointName,
+                    bool success )
+{
+    if ( success ) {
+        fprintf( fp, "\n---> TESTPOINT PASSED (%s{%s} | %s)\n\n", packageName, testPointName, testPointFile );
+    } else {
+        fprintf( fp, "\n---> TESTPOINT FAILED (%s{%s} | %s)\n\n", packageName, testPointName, testPointFile );
+    }
+}
Index: /tags/rel2_1/psLib/test/psTest.h
===================================================================
--- /tags/rel2_1/psLib/test/psTest.h	(revision 1553)
+++ /tags/rel2_1/psLib/test/psTest.h	(revision 1553)
@@ -0,0 +1,81 @@
+
+#ifndef PSTEST_H
+#define PSTEST_H
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#define printPositiveTestHeader(filePtr, packageName, testPointName) \
+p_printPositiveTestHeader(filePtr, __FILE__, packageName, testPointName)
+
+#define printNegativeTestHeader(filePtr, packageName, testPointName, expectedError, exitValue) \
+p_printNegativeTestHeader(filePtr, __FILE__, packageName, testPointName, expectedError, exitValue)
+
+#define printFooter(filePtr, packageName, testPointName, success) \
+p_printFooter(filePtr, __FILE__, packageName, testPointName, success)
+
+typedef int (*testFcn)(void);
+
+typedef struct
+{
+    testFcn     fcn;
+    int         testPointNumber;
+    const char* testPointName;
+    int         expectedReturn;
+    bool        isDuplicateEntry;
+}
+testDescription;
+
+#define runTest(filePtr, packageName, testPointName, fcn, expectedReturn, useFork) \
+p_runTest(filePtr, __FILE__, packageName, testPointName, fcn, expectedReturn, useFork)
+
+#define runTestSuite(filePtr, packageName, tests, argc, argv) \
+p_runTestSuite(filePtr, __FILE__, packageName, tests, argc, argv)
+
+
+/////////////////////////// PRIVATE FUNCTIONS //////////////////////////////
+
+bool p_runTest(
+    FILE *fp,
+    const char* testPointFile,
+    const char* packageName,
+    const char* testPointName,
+    testFcn fcn,
+    int expectedReturn,
+    bool useFork
+);
+
+bool p_runTestSuite(
+    FILE *fp,
+    const char* testPointFile,
+    const char* packageName,
+    testDescription tests[],
+    int argc,
+    char * const argv[]
+);
+
+void p_printPositiveTestHeader(
+    FILE *fp,
+    const char* testPointFile,
+    const char* packageName,
+    const char* testPointName
+);
+
+void p_printNegativeTestHeader(
+    FILE *fp,
+    const char* testPointFile,
+    const char* packageName,
+    const char* testPointName,
+    const char* expectedError,
+    int exitValue
+);
+
+void p_printFooter(
+    FILE *fp,
+    const char* testPointFile,
+    const char* packageName,
+    const char* testPointName,
+    bool success
+);
+
+#endif
Index: /tags/rel2_1/psLib/test/runTest
===================================================================
--- /tags/rel2_1/psLib/test/runTest	(revision 1553)
+++ /tags/rel2_1/psLib/test/runTest	(revision 1553)
@@ -0,0 +1,388 @@
+#!/usr/bin/perl
+#
+#  This is a perl script to execute a single test driver program.  The script
+#  will examine the return value of the test driver and capture STDOUT, STDERR
+#  to files.  If the return value of the test driver is not zero, the test is
+#  deemed a failure.  STDOUT and STDERR files will be place in a subdirectory
+#  named temp and the files will be compared with verified STDOUT, STDERR files
+#  in a subdirectory named verified.  If there are no STDOUT, STDERR files in
+#  the verified directory, the captured STDOUT, STDERR files will be scanned
+#  for words which indicate a failure.
+#
+#  Assumptions:  A verified subdirectory with STDOUT, STDERR files exists for
+#                the test driver specified in the arguements if an exact
+#                match of the streams STDOUT, STDERR is necessary.
+#
+#  Return values:
+#                 Bit mapped values
+#                 0    Test run successfull and all tests passed
+#                 1    Verified directory did not exist
+#                 2    Verified STDOUT file did not exist
+#                 4    Verified STDERR file did not exist
+#                 8    STDOUT files did not compare
+#                16    STDERR files did not compare
+#                32    Test driver doesn't exist or is not executable
+#                64    STDOUT captured contains error strings
+#               128    STDERR captured contains error strings
+#               256    Test driver did not return zero
+#
+#  SYNOSIS:  runTest testDriverName
+#
+#  $Revison:  $  $Name: not supported by cvs2svn $
+#  $Date: 2004-08-14 02:27:02 $
+#
+#  Copyright 2004 Maui High Performance Computering Center, University of Hawaii
+#
+################################################################################
+
+# Provides functions for handling long command line options
+use Getopt::Long;
+
+# Assign variables based on the presence of command line options to the script
+GetOptions(
+    "reset!"       => \$reset,
+    "resetStderr!" => \$resetStderr,
+    "resetStdout!" => \$resetStdout,
+    "help!"        => \$help
+);
+
+if ($help) {
+    print
+"Usage: runTest [--reset] [--resetStderr] [--resetStdout] testfile(s)\n\n";
+    exit(0);
+}
+
+if ($reset) {
+    $resetStderr = 1;
+    $resetStdout = 1;
+}
+
+# Initialize exit value
+$exitValue = 0;
+
+# Set up the PSLIB_ROOT environment variable if the user doesn't have it set
+if ( !$ENV{'PSLIB_ROOT'} ) {
+
+    # Use the directory directly above test
+    $PSLIB_ROOT = `cd ..;pwd`;
+
+    # Remove newline for the end of path returned
+    chomp($PSLIB_ROOT);
+
+    # Set the environment variable
+    $ENV{'PSLIB_ROOT'} = $PSLIB_ROOT;
+
+    # Display message that PSLIB_ROOT not found and set to
+    print("PSLIB_ROOT not found: set to $PSLIB_ROOT\n");
+}
+
+# Add PSLIB_ROOT/lib to LD_LIBRARY_PATH and DYLD_LIBRARY_PATH environment vars
+$ENV{'LD_LIBRARY_PATH'}   = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'LD_LIBRARY_PATH'}";
+$ENV{'DYLD_LIBRARY_PATH'} = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'DYLD_LIBRARY_PATH'}";
+
+# Loop through the arguements passed to the script
+foreach (@ARGV) {
+    chomp;
+    $testFile = $_;
+
+    # Check if a temp directory already exists in the current work directory
+    if ( !( -e "temp" ) ) {
+
+        # Create temp directory to store STDOUT, STDERR files during test run
+        `mkdir temp`;
+
+        # Display message of new directory created
+        print("Creating temp directory\n");
+    }
+
+    # Check if a verified directory exists in the current work directory
+    if ( !( -e "verified" ) ) {
+
+        # Display message that verified subdirectory doesn't exist
+        print("        Verified directory doesn't exist.\n");
+
+        # Exit script since the test cannot be run with verified files
+        $exitValue = 1;
+    }
+
+    # Check if the test driver file exists and is executable
+    if ( ( -e $testFile ) && ( -x $testFile ) ) {
+
+        # Display message the test driver is being executed
+        print("--- Executing test driver: $testFile\n");
+
+        # Invoke the test driver
+        system("./$testFile 1> temp/$testFile.stdout 2> temp/$testFile.stderr");
+
+        # Check the return value of the test driver.  A value other than 0
+        # indicates failure of the test driver unless the test driver is name
+        # with a leading 'a' which indicates the test driver is expecting an
+        # abort condition to terminate the driver.
+        if (   ( $? != 0 && ( $testFile !~ /^A/i ) )
+            || ( $? == 0 && ( $testFile =~ /^A/i ) ) )
+        {
+
+            # Display failure message with return value to user
+            if ( $? != 0 && ( $testFile !~ /^A/i ) ) {
+                print(
+"        Failed - Test Driver expected 0 return value (Return value $?)\n"
+                );
+            }
+            elsif ( $? == 0 && ( $testFile =~ /^A/i ) ) {
+                print(
+"        Failed - Test Driver expected abort (Return value $?)\n"
+                );
+            }
+            $exitValue |= 256;
+        }
+        else {
+
+            # Test driver succeeded.
+
+            # Create filtered version of stdout and stderr
+
+            # Open the STDOUT file for reading
+            open( OUTFILE, "< temp/$testFile.stdout" );
+
+            # Open mod file to place filtered STDOUT
+            open( MODFILE,  "> temp/$testFile.stdout.mod" );
+            open( MODFILE2, "> verified/$testFile.stdout" ) if $resetStdout;
+
+           # Replace the variable date, time and host information with constants
+            $hostname = `hostname`;
+            chop $hostname;
+            while (<OUTFILE>) {
+                s/\s+\d+:\d+:\d+\w/<TIME>/g;
+                s/\d+:\d+:\d+/<DATE>/g;
+                s/$hostname/<HOST>/g;
+                s/: Line \d+/: Line <LINENO>/g;
+                s/\:\d+/\:<LINENO>/g;
+                s/allocate \d+ bytes at/allocate <N> bytes at/g;
+
+              # Filter lines with malloc.  This is an artifact of memory testing
+              # with the Mac testbed
+                if ( !m/\*\*\*\smalloc/ ) {
+                    print MODFILE ($_);
+                    print MODFILE2 ($_) if $resetStdout;
+                }
+            }
+
+            # Close mod file
+            close(MODFILE);
+            close(MODFILE2) if $resetStdout;
+
+            # Close STDERR file
+            close(OUTFILE);
+
+            # Open the STDERR file for reading
+            open( OUTFILE, "< temp/$testFile.stderr" );
+
+            # Open mod file to place filtered STDERR
+            open( MODFILE,  "> temp/$testFile.stderr.mod" );
+            open( MODFILE2, "> verified/$testFile.stderr" ) if $resetStderr;
+
+           # Replace the variable date, time and host information with constants
+            while (<OUTFILE>) {
+                s/\s+\d+:\d+:\d+\w/<TIME>/g;
+                s/\d+:\d+:\d+/<DATE>/g;
+                s/$hostname/<HOST>/g;
+                s/: Line \d+/: Line <LINENO>/g;
+                s/\:\d+/\:<LINENO>/g;
+                s/allocate \d+ bytes at/allocate <N> bytes at/g;
+
+              # Filter lines with malloc.  This is an artifact of memory testing
+              # with the Mac testbed
+                if ( !m/\*\*\*\smalloc/ ) {
+                    print MODFILE ($_);
+                    print MODFILE2 ($_) if $resetStderr;
+                }
+            }
+
+            # Close mod file
+            close(MODFILE);
+            close(MODFILE2) if $resetStderr;
+
+            # Close STDERR file
+            close(OUTFILE);
+
+            # Compare STDOUT capture with verified file
+            $exitValue |= &compareStream("verified/$testFile.stdout");
+
+            # Check exit value to determine if verified file doesn't exist
+            if ( $exitValue & 2 ) {
+
+                # STDOUT verified doesn't exist.  Search STDOUT capture
+                # for strings indicating error or failure
+                $exitValue |= &errorStrSearch("$testFile.stdout");
+            }
+
+            # Compare STDERR capture with verified file
+            $exitValue |= &compareStream("verified/$testFile.stderr");
+
+            # Check exit value to determine if verified file doesn't exist
+            if ( $exitValue & 4 ) {
+
+                # STDERR verified doesn't exist.  Search STDERR capture
+                # for strings indicating error or failure
+                $exitValue |= &errorStrSearch("$testFile.stderr");
+            }
+        }
+    }
+    else {
+
+        # Since test driver doesn't exist or is not executable then display
+        # message to user.
+        print(
+"        Need to specify an executable test file within directory.\n"
+        );
+
+        # Exit value set to indicate test driver doesn't exist or not executable
+        $exitValue |= 32;
+    }
+}
+
+# Exit for the script with exit value
+# Ignore the first three bit flags in exitValue since there are not indicators
+# of a failed test
+if ( ( $exitValue >> 3 ) != 0 ) {
+    print("Test failed - return status = $exitValue\n\n");
+}
+else {
+    print("Test successful\n\n");
+}
+exit($exitValue);
+
+################################################################################
+#
+#  SUBROUTINE: errorStrSearch
+#
+#      Description:  This subroutine will search the file specified in its
+#                    parameter for error strings and if they do exists
+#                    the appropriate value will be returned.
+#
+#      Parameter(s): fileName - input file to search for strings
+#
+#      Return:   0  -  No error strings found
+#               64  -  Error strings found in STDOUT
+#              128  -  Error strings found in STDERR
+#
+###############################################################################
+
+sub errorStrSearch {
+    local ($fileName)  = @_;
+    local ($returnVal) = 0;
+
+    # Open the captured file
+    open( CAPT_FILE, "<temp/$fileName" );
+
+    # Scan through all the lines of the file searching for error strings
+    while (<CAPT_FILE>) {
+        if (   m/FAIL/i
+            || m/FAULT/i
+            || m/ERROR/i
+            || m/Not Found/i
+            || m/SIGNAL/i
+            || m/NO SUCH FILE/i
+            || m/\|E\|/i
+            || m/\|A\|/i )
+        {
+            if ( $fileName =~ m/out/ ) {
+                print(
+                    "        Failed - File $fileName contains error strings.\n"
+                );
+                $returnVal = 64;
+            }
+            elsif ( $fileName =~ m/err/ ) {
+                print(
+                    "        Failed - File $fileName contains error strings.\n"
+                );
+                $returnVal = 128;
+            }
+            last;
+        }
+    }
+
+    # Close the capture file
+    close(CAPT_FILE);
+
+    # Return the return value
+    return ($returnVal);
+}
+
+################################################################################
+#
+#  SUBROUTINE: compareStream
+#
+#      Description:  This subroutine will compare the captured stream file with
+#                    a file in the verified directory if one exists.
+#
+#      Parameter(s): streamFile - input file to compare
+#
+#      Return:   0  -  Compare successful
+#                2  -  STDOUT verified file doesn't exist
+#                4  -  STDERR verified file doesn't exist
+#                8  -  STDOUT verified file doesn't compare
+#               16  -  STDERR verified file doesn't compare
+#
+###############################################################################
+
+sub compareStream {
+    local ($streamFile) = @_;
+    local ($returnVal)  = 0;
+    local ($tempFile)   = "";
+
+    # Check for existence of verified STD stream files
+    if ( !( -e $streamFile ) ) {
+
+        # Display message to user that verified STDOUT file doesn't exist
+        print("        File $streamFile doesn't exist.\n");
+
+        # Set exit value bit 1 to indicate proper failure
+        if ( $streamFile =~ /out$/ ) {
+            $returnVal |= 2;
+        }
+        elsif ( $streamFile =~ /err$/ ) {
+            $returnVal |= 4;
+        }
+    }
+    else {
+
+        # Verified STD stream file exists
+
+        # Create name of the temp file to compare
+        $tempFile = $streamFile;
+        $tempFile =~ s/verified/temp/;
+        $tempFile = $tempFile . ".mod";
+
+        # Perform difference on the STD stream files
+        $diffstdout = `diff $streamFile $tempFile`;
+
+        # Check the return value of the difference
+        if ( $? != 0 ) {
+
+            # Difference of STD stream files failed
+
+            # Check for STDOUT in file name to convey appropirate return value
+            if ( $streamFile =~ /out$/ ) {
+
+                # Display message of the failure of difference to user
+                print("        Failed - STDOUT difference\n$diffstdout\n");
+
+                # Exit value to indicate STDOUT did not compare
+                $returnVal |= 8;
+            }
+            elsif ( $streamFile =~ /err$/ ) {
+
+                # Display message of the failure of difference to user
+                print("        Failed - STDERR difference\n$diffstdout\n");
+
+                # Exit value to indicate STDERR did not compare
+                $returnVal |= 16;
+            }
+        }
+    }
+
+    # Return the result of the compare
+    return ($returnVal);
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/.cvsignore
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/.cvsignore	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/.cvsignore	(revision 1553)
@@ -0,0 +1,24 @@
+temp
+atst_psAbort_01
+atst_psAbort_02
+atst_psAbort_03
+tst_psError
+tst_psHash00
+tst_psHash01
+tst_psHash02
+tst_psHash03
+tst_psHash04
+tst_psLogMsg00
+tst_psLogMsg01
+tst_psLogMsg02
+tst_psLogMsg03
+tst_psMemory
+tst_psStringCopy
+tst_psTrace00
+tst_psTrace01
+tst_psTrace02
+tst_psTrace02_OUT
+tst_psTrace03
+tst_psTrace04
+core*
+log.txt
Index: /tags/rel2_1/psLib/test/sysUtils/Makefile
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/Makefile	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/Makefile	(revision 1553)
@@ -0,0 +1,58 @@
+################################################################################
+##
+##  Makefile:   test/sysUtils
+##
+##  $Revision: 1.18 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-08-09 20:38:11 $
+##
+##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##
+###############################################################################
+
+ifndef prefix
+    export prefix=$(shell cd ../..;pwd)
+endif
+
+include ../../src/Makefile.Globals
+
+CFLAGS := -I../../include $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+
+TARGET = atst_psAbort_01  \
+         atst_psAbort_02  \
+         atst_psAbort_03  \
+         tst_psMemory     \
+         tst_psError      \
+         tst_psLogMsg00   \
+         tst_psLogMsg01   \
+         tst_psLogMsg02   \
+         tst_psLogMsg03   \
+         tst_psStringCopy \
+         tst_psTrace00    \
+         tst_psTrace01    \
+         tst_psTrace02    \
+         tst_psTrace03    \
+         tst_psTrace04
+
+OBJS = $(addsuffix .o,$(TARGET))
+
+all: $(TARGET)
+
+clean:
+	@echo "    Deleting executable and binary files for 'test/collections'"
+	$(RM) $(OBJS)
+
+distclean: clean
+	$(RM) $(TARGET)
+
+install: $(testbindir) $(testbindir)/verified $(TARGET)
+	install $(TARGET) $(testbindir)
+	install verified/*.stderr verified/*.stdout $(testbindir)/verified
+
+$(testbindir):
+	mkdir -p $(testbindir)
+
+$(testbindir)/verified:
+	mkdir -p $(testbindir)/verified
+
+
Index: /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_01.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_01.c	(revision 1553)
@@ -0,0 +1,43 @@
+/** @file  atst_psAbort_01.c
+ *
+ *  @brief Test driver for psAbort function
+ *
+ *  This test drivers contains the following test points for psAbort
+ *     1) Multiple type values in abort message
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main ( int argc,
+           char *argv[]
+         )
+{
+    int   intval = 1;
+    long  longval = 2;
+    float floatval = 3.01;
+    char  charval = 'E';
+    char  *stringval = "E R R O R";
+
+    // Test point #1 Multiple type values placed in the error string
+    printPositiveTestHeader(stderr, "psAbort","Multiple type values in abort message");
+    psAbort(__func__,
+            "ALL TYPES intval = %d longval = %ld floatval = %f charval = %c strval = %s",
+            intval, longval, floatval, charval, stringval );
+    // Since abort should never get to the next statement it would indicate
+    // a test failure
+    printFooter(stderr,"psAbort","Multiple type values in abort message",false);
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_02.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_02.c	(revision 1553)
@@ -0,0 +1,35 @@
+/** @file  atst_psAbort_02.c
+ *
+ *  @brief Test driver for psAbort function
+ *
+ *  This test drivers contains the following test points for psAbort
+ *     2) String values in error message
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main ( int argc,
+           char *argv[]
+         )
+{
+    // Test point #2 String values in abort message
+    printPositiveTestHeader(stderr,"psAbort","String values in abort message");
+    psAbort(PS_STRING(__LINE__), "NO_VALUES");
+    // Since abort should never get to the next statement it would indicate
+    // a test failure
+    printFooter(stderr,"psAbort","String values in abort message",false);
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_03.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/atst_psAbort_03.c	(revision 1553)
@@ -0,0 +1,35 @@
+/** @file  atst_psAbort_02.c
+ *
+ *  @brief Test driver for psAbort function
+ *
+ *  This test drivers contains the following test points for psAbort
+ *     3) Empty strings in abort message
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pslib.h"
+#include "psTest.h"
+
+int main ( int argc,
+           char *argv[]
+         )
+{
+    // Test point #3 Empty strings in abort message
+    printPositiveTestHeader(stderr, "psAbort","Empty strings in abort message");
+    psAbort("", "");
+    // Since abort should never get to the next statement it would indicate
+    // a test failure
+    printFooter(stderr, "psAbort","Empty strings in abort message",false);
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psError.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psError.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psError.c	(revision 1553)
@@ -0,0 +1,63 @@
+/** @file  tst_psError.c
+ *
+ *  @brief Test driver for psError function
+ *
+ *  This test driver contains the following test points for psError
+ *     1)  Multiple type values in error message
+ *     2)  String values in error message
+ *     3)  Empty strings in error message
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.5 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main(int argc,
+         char* argv[])
+{
+
+    int  intval=1;
+    long longval = 2;
+    float floatval = 3.01;
+    char  charval = 'E';
+    char *stringval = "E R R O R";
+    int   memBlockAllocated = 0;
+    psMemBlock  ***memBlockPtr = NULL;
+
+    // Test point #1 Multiple type values placed in the error string
+    printPositiveTestHeader(stderr,"psError","Multiple type values in error message");
+    psError(__func__,
+            "ALL TYPES intval = %d longval = %ld floatval = %f charval = %c strval = %s",
+            intval,longval,floatval,charval,stringval);
+    printFooter(stderr, "psError","Multiple type values in error message",true);
+
+    // Test point #2 String values in error message
+    printPositiveTestHeader(stderr, "psError","String values in error message");
+    psError(PS_STRING(__LINE__),"NO VALUES");
+    printFooter(stderr, "psError","String values in error message",true);
+
+    // Test point #3 Empty strings in error message
+    printPositiveTestHeader(stderr, "psError","Empty strings in error message");
+    psError("","");
+    printFooter(stderr, "psError","Empty strings in error message",true);
+
+    // Check for memory leaks
+    memBlockAllocated = psMemCheckLeaks(0, memBlockPtr, stderr);
+    if ( memBlockAllocated != 0 ) {
+        fprintf(stderr,"FAIL - Memory leak detected - Number of blocks = %d\n",memBlockAllocated);
+    }
+    // Check for memory corruption and abort if detected
+    memBlockAllocated = psMemCheckCorruption(1);
+
+    return 0;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg00.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg00.c	(revision 1553)
@@ -0,0 +1,70 @@
+/*****************************************************************************
+    This code will test whether trace levels can be set successfully.
+    This code will test whether trace messages can be displayed with printf
+    style string.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+void myLogMsg(const char *name,
+              int level,
+              const char *fmt,
+              ...)
+{
+    va_list ap;
+
+    // Test whether psLogMsgV() accept a va_list for output variables.
+    va_start(ap, fmt);
+    psLogMsgV(name, level, fmt, ap);
+    va_end(ap);
+}
+
+int main()
+{
+    int i = 0;
+    int testStatus = true;
+    int currentId = psMemGetId();
+
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "default log levels, printf-style strings");
+
+    // Send a log messages for levels 0:9.  Only the first four messages
+    // should actually be displayed.
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d %f %s\n", i,
+                 (float) i, "beep beep");
+    }
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "default log levels",
+                testStatus);
+
+
+    // Test whether psLogMsgV() accept a va_list for output variables.
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "default log levels, psVLogMsg()");
+
+    // Send a log messages for levels 0:9.  Only the first four messages
+    // should actually be displayed.
+    for (i=0;i<10;i++) {
+        myLogMsg(__func__, i, "Hello World!  My level is %d %f %s\n", i,
+                 (float) i, "beep beep");
+    }
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "default log levels",
+                testStatus);
+
+    if (psMemCheckLeaks(currentId,NULL,NULL) != 0) {
+        psAbort(__func__,"Memory Leaks!");
+    }
+    psMemCheckCorruption(1);
+
+    return(!testStatus);
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg01.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg01.c	(revision 1553)
@@ -0,0 +1,43 @@
+/*****************************************************************************
+    This code tests whether trace levels can be set successfully.
+ 
+ NOTE: This code must be modified once printFooter() is modified to include
+ a parameter that indicates we don't know whether the test passed or failed.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    int i = 0;
+    int testStatus = true;
+    int currentId = psMemGetId();
+
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "psLogSetLevel()");
+
+    psLogSetLevel(9);
+    // Send a log messages for levels 0:9.
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    psLogSetLevel(5);
+    psLogMsg(__func__, 6, "This should not be displayed (level %d)\n", 6);
+    psLogSetLevel(4);
+    psLogMsg(__func__, 4, "This should  be displayed (level %d)\n", 4);
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "psLogSetLevel()",
+                testStatus);
+
+    if (psMemCheckLeaks(currentId,NULL,NULL) != 0) {
+        psAbort(__func__,"Memory Leaks!");
+    }
+    psMemCheckCorruption(1);
+
+    return(!testStatus);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg02.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg02.c	(revision 1553)
@@ -0,0 +1,101 @@
+/*****************************************************************************
+    This code tests whether the log message format can be set.
+ 
+ NOTE: This code must be modified once printFooter() is modified to include
+ a parameter that indicates we don't know whether the test passed or failed.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    int i = 0;
+    int testStatus = true;
+    int currentId = psMemGetId();
+
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "psLogSetFormat()");
+
+
+    fprintf(stderr,"------------- psLogSetFormat() -------------\n");
+    psLogSetFormat("");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(NULL) -------------\n");
+    psLogSetFormat(NULL);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(T) -------------\n");
+    psLogSetFormat("T");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(H) -------------\n");
+    psLogSetFormat("H");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(L) -------------\n");
+    psLogSetFormat("L");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(N) -------------\n");
+    psLogSetFormat("N");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(M) -------------\n");
+    psLogSetFormat("M");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(THLNM) -------------\n");
+    psLogSetFormat("THLNM");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "psLogSetFormat()",
+                testStatus);
+
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "Output Format");
+
+    psLogMsg("Under 15 chars", 0, "Hello World!\n");
+    psLogMsg("This string is more than 15 chars", 0, "Hello World!\n");
+    psLogMsg(__func__, 0, "Line #1\n");
+    psLogMsg(__func__, 0, "Line #2\n");
+    psLogMsg(__func__, 0, "Line #3");
+    psLogMsg(__func__, 0, "Line #4");
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "Output Format",
+                testStatus);
+
+
+    if (psMemCheckLeaks(currentId,NULL,NULL) != 0) {
+        psAbort(__func__,"Memory Leaks!");
+    }
+    psMemCheckCorruption(1);
+
+    return(!testStatus);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg03.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psLogMsg03.c	(revision 1553)
@@ -0,0 +1,72 @@
+/*****************************************************************************
+    This code tests whether the log message can be redirected to STDERR or
+    STDOUT.
+ 
+ NOTE: This code must be modified once printFooter() is modified to include
+ a parameter that indicates we don't know whether the test passed or failed.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    int i = 0;
+    int testStatus = true;
+    int currentId = psMemGetId();
+    FILE* file;
+    char line[256];
+
+    printPositiveTestHeader(stdout,
+                            "psLogMsg functions",
+                            "psLogSetDestination()");
+
+    printf("--------------- psLogSetDestination(PS_LOG_NONE) ----------------\n");
+    psLogSetDestination("none");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("------------- psLogSetDestination(PS_LOG_TO_STDERR) -------------\n");
+    psLogSetDestination("dest:stderr");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("------------- psLogSetDestination(PS_LOG_TO_STDOUT) -------------\n");
+    psLogSetDestination("dest:stdout");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+    printf("--------------- psLogSetDestination(""file:log.txt"") ---------------\n");
+    psLogSetDestination("file:log.txt");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    psLogSetDestination("none");
+    printf("--------------------- The Contents of log.txt -------------------\n");
+    file = fopen("log.txt","r");
+    while ( fgets(line,256,file) != NULL ) {
+        printf("%s",line);
+    }
+    fclose(file);
+
+    printf("--------------- psLogSetDestination(""file:/eva/log.txt"") ----------\n");
+    psLogSetDestination("file:/eva/log.txt");
+    for ( i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World! My level is %d\n", i);
+    }
+
+    printFooter(stdout,
+                "psLogMsg functions",
+                "psLogSetDestination()",
+                testStatus);
+
+    if (psMemCheckLeaks(currentId,NULL,NULL) != 0) {
+        psAbort(__func__,"Memory Leaks!");
+    }
+    psMemCheckCorruption(true);
+
+    return(!testStatus);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psMemory.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psMemory.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psMemory.c	(revision 1553)
@@ -0,0 +1,556 @@
+/** @file  tst_psMemory.c
+*
+*  @brief Contains the tests for psMemory.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-14 02:04:23 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+// need to allow malloc for callback use
+#define PS_ALLOW_MALLOC 1
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdlib.h>
+
+
+#include "psTest.h"
+#include "pslib.h"
+
+static int TPFreeReferencedMemory( void );
+static int TPOutOfMemory( void );
+static int TPReallocOutOfMemory( void );
+static void* TPOutOfMemoryExhaustedCallback( size_t size );
+static int TPCheckBufferPositive( void );
+static int TPrealloc( void );
+static int TPallocCallback( void );
+static psMemoryId memAllocateCallback( const psMemBlock *ptr );
+static psMemoryId memFreeCallback( const psMemBlock *ptr );
+static int TPcheckLeaks( void );
+static int TPmemCorruption( void );
+static int TPmultipleFree( void );
+void memProblemCallback( const psMemBlock *ptr, const char *file, int lineno );
+
+static int problemCallbackCalled = 0;
+static int allocCallbackCalled = 0;
+static int freeCallbackCalled = 0;
+static int exhaustedCallbackCalled = 0;
+
+testDescription tests[] = {
+                              {
+                                  TPCheckBufferPositive, 449, "checkBufferPositive", 0, false
+                              },
+                              {
+                                  TPOutOfMemory, 450, "outOfMemory", -6, false
+                              },
+                              {
+                                  TPReallocOutOfMemory, 562, "reallocOutOfMemory", -6, false
+                              },
+                              {
+                                  TPrealloc, 451, "psRealloc", 0, false
+                              },
+                              {
+                                  TPallocCallback, 452, "allocCallback", 0, false
+                              },
+                              {
+                                  TPallocCallback, 453, "allocCallback2", 0, true
+                              },
+                              {
+                                  TPcheckLeaks, 454, "checkLeaks", 0, false
+                              },
+                              {
+                                  TPmemCorruption, 455, "psMemCorruption", 0, false
+                              },
+                              {
+                                  TPFreeReferencedMemory, 456, "freeReferencedMemory", 0, false
+                              },
+                              {
+                                  TPmultipleFree, 699, "multipleFree", -6, false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+int main( int argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psMemory", tests, argc, argv ) );
+}
+
+// Testpoint #449, psAlloc shall allocate memory blocks writeable by caller.
+int TPCheckBufferPositive( void )
+{
+    int * mem;
+    const int size = 100;
+    int failed = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psAlloc shall allocate memory blocks writeable by caller.\n" );
+
+    mem = ( int* ) psAlloc( size * sizeof( int ) );
+    if ( mem == NULL ) {
+        psError( __FILE__, "psAlloc returned a NULL value in %s!", __func__ );
+        return 1;
+    }
+
+    for ( int index = 0;index < size;index++ ) {
+        mem[ index ] = index;
+    }
+
+    for ( int index = 0;index < size;index++ ) {
+        if ( mem[ index ] != index ) {
+            failed++;
+        }
+    }
+
+    psFree( mem );
+
+    return failed;
+}
+
+int TPFreeReferencedMemory( void )
+{
+    // create memory
+    int * mem;
+    int ref = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "memory reference count shall be incrementable/decrementable" );
+
+    mem = ( int* ) psAlloc( 100 * sizeof( int ) );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 1 ) {
+        psError( __func__, "Expected to buffer reference count to be initially 1, but it was %d.", ref );
+        return 1;
+    }
+
+    psMemIncrRefCounter( mem );
+    psMemIncrRefCounter( mem );
+    psMemIncrRefCounter( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 4 ) {
+        psError( __func__, "Expected to find buffer reference count to be 4, but it was %d.", ref );
+        return 1;
+    }
+
+    psMemDecrRefCounter( mem );
+    psMemDecrRefCounter( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 2 ) {
+        psError( __func__, "Expected to find buffer reference count to be 2, but it was %d.", ref );
+        return 1;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "psFree shall be just decrement a multiple refererenced pointer." );
+
+    psFree( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 1 ) {
+        psError( __func__, "Expected to find buffer reference count to be 1, but it was %d.", ref );
+        return 1;
+    }
+
+    psFree( mem );
+
+    return 0;
+}
+
+// Bug/Task #562 regression test.  Upon requesting more memory than is available, psRealloc shall call
+// the psMemExhaustedCallback.
+int TPReallocOutOfMemory( void )
+{
+    int * mem[ 100 ];
+    psMemExhaustedCallback cb;
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = NULL;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Upon requesting more memory than is available, psRealloc shall call "
+              "the psMemExhaustedCallback.\n" );
+
+    exhaustedCallbackCalled = 0;
+
+    cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( int* ) psAlloc( 10 );
+    }
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( int* ) psRealloc( mem[ lcv ], SIZE_MAX/2 - 1000 );
+    }
+
+    psMemExhaustedCallbackSet( cb );
+
+    if ( exhaustedCallbackCalled == 0 ) {
+        psError( __FILE__, "Called psRealloc with HUGE memory requirement and survived in %s!", __func__ );
+        return 1;
+    }
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        psFree( mem[ lcv ] );
+    }
+
+    return 0;
+}
+// Testpoint #450,  Upon requesting more memory than is available, psalloc shall call
+// the psMemExhaustedCallback.
+int TPOutOfMemory( void )
+{
+    int * mem[ 100 ];
+    psMemExhaustedCallback cb;
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = NULL;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Upon requesting more memory than is available, psalloc shall call "
+              "the psMemExhaustedCallback.\n" );
+
+    exhaustedCallbackCalled = 0;
+
+    cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( int* ) psAlloc( SIZE_MAX/2 - 1000 );
+    }
+
+    psMemExhaustedCallbackSet( cb );
+
+    if ( exhaustedCallbackCalled == 0 ) {
+        psError( __FILE__, "Called psAlloc with HUGE memory requirement and survived in %s!", __func__ );
+        return 1;
+    }
+
+    for ( int lcv = 0; lcv < 100; lcv++ ) {
+        psFree( mem[ lcv ] );
+    }
+
+    return 0;
+}
+
+// Testpoint #451,  psRealloc shall increase/decrease memory buffer while preserving contents
+int TPrealloc( void )
+{
+    int * mem1;
+    int* mem2;
+    int* mem3;
+    const int initialSize = 100;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psRealloc shall increase/decrease memory buffer while "
+              "preserving contents" );
+
+    // allocate buffer with known values.
+    mem1 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+    mem2 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+    mem3 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+    for ( int lcv = 0;lcv < initialSize;lcv++ ) {
+        mem1[ lcv ] = mem2[ lcv ] = mem3[ lcv ] = lcv;
+    }
+
+    psMemCheckCorruption( 1 );
+    psLogMsg( __func__, PS_LOG_INFO, "Expanding memory buffer." );
+
+    // realloc to 2x
+    mem1 = ( int* ) psRealloc( mem1, 2 * initialSize * sizeof( int ) );
+    mem2 = ( int* ) psRealloc( mem2, 2 * initialSize * sizeof( int ) );
+    mem3 = ( int* ) psRealloc( mem3, 2 * initialSize * sizeof( int ) );
+
+    // check values of initial block
+    for ( int i = 0;i < initialSize;i++ ) {
+        if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+            psError( __FILE__, "Realloc didn't preserve the contents with expanding buffer in %s.",
+                     __func__ );
+            break;
+        }
+    }
+
+    psMemCheckCorruption( 1 );
+    psLogMsg( __func__, PS_LOG_INFO, "Shrinking memory buffer." );
+
+    // realloc to 1/2 initial value.
+    mem1 = ( int* ) psRealloc( mem1, ( initialSize / 2 ) * sizeof( int ) );
+    mem2 = ( int* ) psRealloc( mem2, ( initialSize / 2 ) * sizeof( int ) );
+    mem3 = ( int* ) psRealloc( mem3, ( initialSize / 2 ) * sizeof( int ) );
+
+    // check values of initial block
+    for ( int i = 0;i < initialSize / 2;i++ ) {
+        if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+            psError( __FILE__, "Realloc didn't preserve the contents with shrinking buffer in %s.",
+                     __func__ );
+            break;
+        }
+    }
+
+    psFree( mem1 );
+    psFree( mem2 );
+    psFree( mem3 );
+
+    return 0;
+}
+
+int TPallocCallback( void )
+{
+    int * mem1;
+    int* mem2;
+    int* mem3;
+    int currentId = psMemGetId();
+    const int initialSize = 100;
+    int mark;
+
+    allocCallbackCalled = 0;
+    freeCallbackCalled = 0;
+    psMemAllocateCallbackSet( memAllocateCallback );
+    psMemFreeCallbackSet( memFreeCallback );
+
+    psMemAllocateCallbackSetID( currentId + 1 );
+    psMemFreeCallbackSetID( currentId + 1 );
+
+    psLogMsg( __func__, PS_LOG_INFO, "call to psAlloc/psRealloc shall generate a callback if specified "
+              "memory ID is allocated." );
+
+    // allocate buffer with known values.
+    mem1 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+    mem2 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+    mem3 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+
+    psFree( mem1 );
+    psFree( mem2 );
+    psFree( mem3 );
+
+    if ( allocCallbackCalled != 2 || freeCallbackCalled != 2 ) {
+        psError( __FILE__, "alloc/free callbacks were not called the proper number of times in %s",
+                 __func__ );
+        return 1;
+    }
+
+    allocCallbackCalled = 0;
+    freeCallbackCalled = 0;
+
+    mark = psMemGetId();
+
+    mem1 = ( int* ) psAlloc( initialSize * sizeof( int ) );
+
+    psMemAllocateCallbackSetID( mark );
+
+    mem1 = ( int* ) psRealloc( mem1, initialSize * 2 * sizeof( int ) );
+
+    psFree( mem1 );
+
+    if ( allocCallbackCalled != 2 ) {
+        psError( __FILE__, "realloc callbacks were not called the proper number of times in %s",
+                 __func__ );
+        return 1;
+    }
+
+    return 0;
+
+}
+
+int TPcheckLeaks( void )
+{
+    const int numBuffers = 5;
+    int* buffers[ 5 ];
+    int lcv;
+    int currentId = psMemGetId();
+    psMemBlock** blks;
+    int nLeaks = 0;
+    int lineMark = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckLeaks shall return the number of blocks above an ID "
+              "that are still allocated" );
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( int ) );
+    }
+
+    for ( lcv = 1;lcv < numBuffers;lcv++ ) {
+        psFree( buffers[ lcv ] );
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce one instance." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr );
+
+    if ( nLeaks != 1 ) {
+        psError( __FILE__, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError( __FILE__, "psMemCheckLeaks found a leak other than the expected one (line %d vs %d) in %s.",
+                 lineMark, blks[ 0 ] ->lineno, __func__ );
+        return 1;
+    }
+
+    psFree( buffers[ 0 ] );
+    psFree( blks );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Testing psMemCheckLeaks again with a different leak location" );
+    psMemCheckLeaks( currentId, NULL, stderr );
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( int ) );
+    }
+
+    for ( lcv = 0;lcv < numBuffers - 1;lcv++ ) {
+        psFree( buffers[ lcv ] );
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce one error." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr );
+
+    if ( nLeaks != 1 ) {
+        psError( __FILE__, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError( __FILE__, "psMemCheckLeaks found a leak other than the expected one in %s.", __func__ );
+        return 1;
+    }
+
+    psFree( buffers[ 4 ] );
+    psFree( blks );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Testing psMemCheckLeaks again with multiple leak locations." );
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( int ) );
+    }
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        if ( lcv % 2 == 0 ) {
+            psFree( buffers[ lcv ] );
+        }
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce two errors." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr );
+
+    if ( nLeaks != 2 ) {
+        psError( __FILE__, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError( __FILE__, "psMemCheckLeaks found a leak other than the expected one in %s.", __func__ );
+        return 1;
+    }
+
+    psFree( blks );
+    psFree( buffers[ 1 ] );
+    psFree( buffers[ 3 ] );
+
+    return 0;
+}
+
+int TPmemCorruption( void )
+{
+    int * buffer = NULL;
+    int oldValue = 0;
+    int corruptions = 0;
+    psMemProblemCallback cb;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckCorruption shall detect memory corruptions" );
+
+    buffer = psAlloc( sizeof( int ) );
+
+    // cause memory corruption via buffer underflow
+    *buffer = 1;
+    buffer--;
+    oldValue = *buffer;
+    *buffer = 2;
+
+    problemCallbackCalled = 0;
+    cb = psMemProblemCallbackSet( memProblemCallback );
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckCorruption should output an error message and "
+              "memProblemCallback callback should be called." );
+
+    corruptions = psMemCheckCorruption( 0 );
+
+    // restore the memory problem callback
+    psMemProblemCallbackSet( cb );
+
+    // restore the value, 'uncorrupting' the buffer
+    *buffer = oldValue;
+    buffer++;
+
+    psFree( buffer );
+
+    if ( corruptions != 1 ) {
+        psError( __FILE__, "Expected one memory corruption but found %d in %s.",
+                 corruptions, __func__ );
+        return 1;
+    }
+
+    if ( problemCallbackCalled != 1 ) {
+        psError( __FILE__, "The memProblemCallback was not invoked but should have been in %s",
+                 __func__ );
+        return 1;
+    }
+
+    return 0;
+
+}
+
+void memProblemCallback( const psMemBlock *ptr, const char *file, int lineno )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "memory callback called for id %d (%s:%d).",
+              ptr->id, file, lineno );
+    problemCallbackCalled++;
+    return ;
+}
+
+psMemoryId memAllocateCallback( const psMemBlock *ptr )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "block %d was (re)allocated", ptr->id );
+    allocCallbackCalled++;
+    return 1;
+}
+
+psMemoryId memFreeCallback( const psMemBlock *ptr )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "block %d was freed", ptr->id );
+    freeCallbackCalled++;
+    return 1;
+}
+
+void* TPOutOfMemoryExhaustedCallback( size_t size )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "Custom MemExhaustedCallback was invoked." );
+    exhaustedCallbackCalled++;
+    return NULL;
+}
+
+int TPmultipleFree( void )
+{
+
+    void * buffer = psAlloc( 1024 );
+
+    psFree( buffer );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Next should be an error about multiple freeing." );
+    psFree( buffer );
+
+    return 0;
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psString.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psString.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psString.c	(revision 1553)
@@ -0,0 +1,203 @@
+/** @file  tst_psString.c
+ *
+ *  @brief Test driver for psStringCopy functions
+ *
+ *  This test driver contains the following test points for psStringCopy
+ *  and psStringNCopy functions.
+ *    1) Verify string copy - psStringCopy
+ *    2) Verify empty string copy - psStringCopy
+ *    3) Verify string copy with length - psStringNCopy
+ *    4) Verify empty string copy with length - psStringNCopy
+ *    5) Copy string to larger string - psStringNCopy
+ *    6) Copy string with negative size - psStringNCopy
+ *    7) Verifiy creation of string literal - PS_STRING
+ * 
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main( int argc,
+          char * argv[] )
+{
+    bool  tpResult = false;
+    char  stringval[20] = "E R R O R";
+    char  stringval1[20] = "e r r o r";
+    char  *stringvalnocopy = "F A I L";
+    char  *substringval = "e r r";
+    int   substringlen = 6;
+    char  *emptyval = "";
+    int   tpFails = 0;
+    char  *strResult;
+    int   increaseSize = 5;
+    int   negativeSize = -5;
+    int   result = 0;
+    int   result1 = 0;
+    int   memBlockAllocated = 0;
+    psMemBlock ***memBlockPtr = NULL;
+
+    // Test point #1 Verify string copy - psStringCopy
+    printPositiveTestHeader(stderr,"psStringCopy","Verify string copy");
+    strResult = psStringCopy(stringval);
+    // Perform string compare
+    result = strcmp(strResult, stringval);
+    // Modify original string
+    stringval[0]='G';
+    result1 = strcmp(strResult, stringval);
+    stringval[0]='E';
+    if ( ( result != 0 ) || ( result1 == 0) ) {
+        fprintf(stderr, "Failed test point #1 strcmp result = %d expected 0\n",result);
+        fprintf(stderr, "                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr, "             changed strcmp result = %d expected 1\n",result1);
+        fprintf(stderr, "             changed           src = %s expected %s\n",strResult,
+                stringval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringCopy","Verify string copy", tpResult);
+
+    // Test point #2 Verify empty string copy - psStringCopy
+    printPositiveTestHeader(stderr,"psStringCopy","Verify empty string copy");
+    strResult = psStringCopy(emptyval);
+    // Perform string compare
+    result = strcmp(strResult, emptyval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #2 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, emptyval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringCopy","Verify empty string copy", tpResult);
+
+    // Test point #3 Verify string copy with length - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy","Verify string copy with length");
+    strResult = psStringNCopy(stringval1, substringlen);
+    // Perform string compare and get string length
+    result = strncmp(strResult, substringval, substringlen);
+    // Change original string
+    stringval1[0] = 'g';
+    result1 = strncmp(strResult, substringval, substringlen);
+    if ( ( result != 0 ) || ( result1 != 0 ) ) {
+        fprintf(stderr,"Failed test point #3 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        fprintf(stderr,"             changed strcmp result = %d expected 0\n",result1);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy","Verify string copy with length", tpResult);
+
+    // Test point #4 Verify empty string copy with length - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Verify empty string copy with length");
+    strResult = psStringNCopy(stringvalnocopy, 0);
+    // Perform string compare and get sting length
+    result = strcmp(strResult, stringvalnocopy);
+    result1 = strlen(strResult);
+    if ( result == 0 ) {
+        fprintf(stderr,"Failed test point #4 strcmp result = %d didn't expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s didn't expected %s\n",
+                strResult, stringvalnocopy);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy","Verify empty string copy with length", tpResult);
+
+    // Test point #5 Copy string to larger string - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Copy string to larger string");
+    strResult = psStringNCopy(stringval, (strlen(stringval) + increaseSize));
+    // Perform string compare and get string length
+    result = strcmp(strResult, stringval);
+    result1 = strlen(strResult);
+    // The strings should still compare
+    if ( ( result != 0 ) ||
+            ( result1 != strlen(stringval) ) ) {
+        fprintf(stderr,"Failed test point #5 strcmp result = %d expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr,"                     strlne result = %d expected %d\n",result1,
+                (int)strlen(stringval));
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy", "Copy string to larger string", tpResult);
+
+    // Test point #6 Copy string with negative size - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Copy string with negative size");
+    strResult = psStringNCopy(stringval, negativeSize);
+    if ( strResult != NULL ) {
+        fprintf(stderr,"Failed test point #6 return value = %ld expected NULL\n",
+                (unsigned long)strResult);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Memory should not have been allocated
+    printFooter(stderr, "psStringNCopy", "Copy string with negative size", tpResult);
+
+    // Test point #7 Verify creation of string literal - PS_STRING
+    printPositiveTestHeader(stderr,"PS_STRING","Verify creation of string literal");
+    strResult = PS_STRING(E R R O R);
+    result = strcmp(strResult, stringval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #7 strcmp result = %d expected %d",result,0);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Memory should not have been allocated
+    printFooter(stderr, "PS_STRING", "Verify creation of string literal", tpResult);
+
+    // Check for memory leaks
+    memBlockAllocated = psMemCheckLeaks(0, memBlockPtr, stderr);
+    if ( memBlockAllocated != 0 ) {
+        fprintf(stderr,"Failed - Memory leaks detected - Blocks still allocated = %d\n",
+                memBlockAllocated);
+        tpFails++;
+    }
+
+    // Display test driver fail message if tpFail not zero
+    if ( tpFails != 0 ) {
+        fprintf(stderr,"Failed test driver  testpoint fail = %d expected %d\n",
+                tpFails, 0);
+    }
+
+    // Return number of test points which failed
+    return tpFails;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psStringCopy.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psStringCopy.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psStringCopy.c	(revision 1553)
@@ -0,0 +1,203 @@
+/** @file  tst_psString.c
+ *
+ *  @brief Test driver for psStringCopy functions
+ *
+ *  This test driver contains the following test points for psStringCopy
+ *  and psStringNCopy functions.
+ *    1) Verify string copy - psStringCopy
+ *    2) Verify empty string copy - psStringCopy
+ *    3) Verify string copy with length - psStringNCopy
+ *    4) Verify empty string copy with length - psStringNCopy
+ *    5) Copy string to larger string - psStringNCopy
+ *    6) Copy string with negative size - psStringNCopy
+ *    7) Verifiy creation of string literal - PS_STRING
+ * 
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2004-08-06 22:34:06 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main( int argc,
+          char * argv[] )
+{
+    bool  tpResult = false;
+    char  stringval[20] = "E R R O R";
+    char  stringval1[20] = "e r r o r";
+    char  *stringvalnocopy = "F A I L";
+    char  *substringval = "e r r";
+    int   substringlen = 6;
+    char  *emptyval = "";
+    int   tpFails = 0;
+    char  *strResult;
+    int   increaseSize = 5;
+    int   negativeSize = -5;
+    int   result = 0;
+    int   result1 = 0;
+    int   memBlockAllocated = 0;
+    psMemBlock ***memBlockPtr = NULL;
+
+    // Test point #1 Verify string copy - psStringCopy
+    printPositiveTestHeader(stderr,"psStringCopy","Verify string copy");
+    strResult = psStringCopy(stringval);
+    // Perform string compare
+    result = strcmp(strResult, stringval);
+    // Modify original string
+    stringval[0]='G';
+    result1 = strcmp(strResult, stringval);
+    stringval[0]='E';
+    if ( ( result != 0 ) || ( result1 == 0) ) {
+        fprintf(stderr, "Failed test point #1 strcmp result = %d expected 0\n",result);
+        fprintf(stderr, "                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr, "             changed strcmp result = %d expected 1\n",result1);
+        fprintf(stderr, "             changed           src = %s expected %s\n",strResult,
+                stringval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringCopy","Verify string copy", tpResult);
+
+    // Test point #2 Verify empty string copy - psStringCopy
+    printPositiveTestHeader(stderr,"psStringCopy","Verify empty string copy");
+    strResult = psStringCopy(emptyval);
+    // Perform string compare
+    result = strcmp(strResult, emptyval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #2 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, emptyval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringCopy","Verify empty string copy", tpResult);
+
+    // Test point #3 Verify string copy with length - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy","Verify string copy with length");
+    strResult = psStringNCopy(stringval1, substringlen);
+    // Perform string compare and get string length
+    result = strncmp(strResult, substringval, substringlen);
+    // Change original string
+    stringval1[0] = 'g';
+    result1 = strncmp(strResult, substringval, substringlen);
+    if ( ( result != 0 ) || ( result1 != 0 ) ) {
+        fprintf(stderr,"Failed test point #3 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        fprintf(stderr,"             changed strcmp result = %d expected 0\n",result1);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory allocated
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy","Verify string copy with length", tpResult);
+
+    // Test point #4 Verify empty string copy with length - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Verify empty string copy with length");
+    strResult = psStringNCopy(stringvalnocopy, 0);
+    // Perform string compare and get sting length
+    result = strcmp(strResult, stringvalnocopy);
+    result1 = strlen(strResult);
+    if ( result == 0 ) {
+        fprintf(stderr,"Failed test point #4 strcmp result = %d didn't expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s didn't expected %s\n",
+                strResult, stringvalnocopy);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy","Verify empty string copy with length", tpResult);
+
+    // Test point #5 Copy string to larger string - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Copy string to larger string");
+    strResult = psStringNCopy(stringval, (strlen(stringval) + increaseSize));
+    // Perform string compare and get string length
+    result = strcmp(strResult, stringval);
+    result1 = strlen(strResult);
+    // The strings should still compare
+    if ( ( result != 0 ) ||
+            ( result1 != strlen(stringval) ) ) {
+        fprintf(stderr,"Failed test point #5 strcmp result = %d expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr,"                     strlne result = %d expected %d\n",result1,
+                (int)strlen(stringval));
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Free memory
+    psFree(strResult);
+    printFooter(stderr, "psStringNCopy", "Copy string to larger string", tpResult);
+
+    // Test point #6 Copy string with negative size - psStringNCopy
+    printPositiveTestHeader(stderr,"psStringNCopy", "Copy string with negative size");
+    strResult = psStringNCopy(stringval, negativeSize);
+    if ( strResult != NULL ) {
+        fprintf(stderr,"Failed test point #6 return value = %ld expected NULL\n",
+                (unsigned long)strResult);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Memory should not have been allocated
+    printFooter(stderr, "psStringNCopy", "Copy string with negative size", tpResult);
+
+    // Test point #7 Verify creation of string literal - PS_STRING
+    printPositiveTestHeader(stderr,"PS_STRING","Verify creation of string literal");
+    strResult = PS_STRING(E R R O R);
+    result = strcmp(strResult, stringval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #7 strcmp result = %d expected %d",result,0);
+        tpResult = false;
+        tpFails++;
+    } else {
+        tpResult = true;
+    }
+    // Memory should not have been allocated
+    printFooter(stderr, "PS_STRING", "Verify creation of string literal", tpResult);
+
+    // Check for memory leaks
+    memBlockAllocated = psMemCheckLeaks(0, memBlockPtr, stderr);
+    if ( memBlockAllocated != 0 ) {
+        fprintf(stderr,"Failed - Memory leaks detected - Blocks still allocated = %d\n",
+                memBlockAllocated);
+        tpFails++;
+    }
+
+    // Display test driver fail message if tpFail not zero
+    if ( tpFails != 0 ) {
+        fprintf(stderr,"Failed test driver  testpoint fail = %d expected %d\n",
+                tpFails, 0);
+    }
+
+    // Return number of test points which failed
+    return tpFails;
+}
+
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psTrace00.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psTrace00.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psTrace00.c	(revision 1553)
@@ -0,0 +1,62 @@
+/*****************************************************************************
+    This code will test whether trace levels can be set successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    int i = 0;
+    int lev = 0;
+    int testStatus = true;
+
+    printPositiveTestHeader(stdout,
+                            "psTrace functions",
+                            "psTraceSetLevel() and psTraceGetLevel()");
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".", i);
+        lev = psTraceGetLevel(".");
+        if (lev != i) {
+            printf("ERROR: (.) expected trace level was %d, actual was %d\n",
+                   i, lev);
+            testStatus = false;
+        }
+    }
+    (void)psTraceSetLevel(".", 3);
+
+    for (i=5;i<10;i++) {
+        (void)psTraceSetLevel(".NODE00", i);
+        lev = psTraceGetLevel(".NODE00");
+        if (lev != i) {
+            printf("ERROR: (.NODE00) expected trace level was %d, actual was %d\n",
+                   i, lev);
+            testStatus = false;
+        }
+
+        lev = psTraceGetLevel(".");
+        if (lev != 3) {
+            printf("ERROR: (.) expected trace level was %d, actual was %d\n",
+                   i, 3);
+            testStatus = false;
+        }
+    }
+
+
+    (void)psTraceSetLevel(".NODE00.NODE01", 4);
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".NODE00.NODE01", i);
+        lev = psTraceGetLevel(".NODE00.NODE01");
+        if (lev != i) {
+            printf("ERROR: (.NODE00.NODE01) expected trace level was %d, actual was %d\n",
+                   i, lev);
+            testStatus = false;
+        }
+    }
+
+    printFooter(stdout,
+                "psTrace functions",
+                "Testing psTraceSetLevel and psTraceGetLevel",
+                testStatus);
+    return(!testStatus);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psTrace01.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psTrace01.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psTrace01.c	(revision 1553)
@@ -0,0 +1,56 @@
+/*****************************************************************************
+    This code will test whether trace levels can be reset successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    int i = 0;
+    int lev = 0;
+    int successFlag = true;
+
+    printPositiveTestHeader(stdout,
+                            "psTrace functions",
+                            "psTraceReset()");
+
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".", i);
+        psTraceReset();
+
+        lev = psTraceGetLevel(".");
+        if (lev != PS_DEFAULT_TRACE_LEVEL) {
+            printf("ERROR: expected trace level was %d, actual was %d\n",
+                   i, lev);
+            successFlag = false;
+        }
+    }
+    (void)psTraceSetLevel(".", 5);
+    (void)psTraceSetLevel(".a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+    (void)psTraceSetLevel(".a.b.c", 2);
+    if ((5 != psTraceGetLevel(".")) ||
+            (4 != psTraceGetLevel(".a")) ||
+            (3 != psTraceGetLevel(".a.b")) ||
+            (2 != psTraceGetLevel(".a.b.c"))) {
+        printf("ERROR: trace levels were not settable?\n");
+        successFlag = false;
+    }
+
+    psTraceReset();
+    if ((PS_DEFAULT_TRACE_LEVEL != psTraceGetLevel(".")) ||
+            (PS_DEFAULT_TRACE_LEVEL != psTraceGetLevel(".a")) ||
+            (PS_DEFAULT_TRACE_LEVEL != psTraceGetLevel(".a.b")) ||
+            (PS_DEFAULT_TRACE_LEVEL != psTraceGetLevel(".a.b.c"))) {
+        printf("ERROR: trace levels were not reset properly\n");
+        successFlag = false;
+    }
+
+    printFooter(stdout,
+                "psTrace functions",
+                "psTraceReset()",
+                successFlag);
+
+    return(!successFlag);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psTrace02.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psTrace02.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psTrace02.c	(revision 1553)
@@ -0,0 +1,61 @@
+/*****************************************************************************
+    This code will test whether trace messages can be successfully displayed
+    and not displayed.
+ 
+    NOTE: We must verify the output for the tst_psTrace02_OUT somewhere.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    FILE *fp;
+    int nb = 0;
+
+    fp = fopen("tst_psTrace02_OUT", "w");
+    for (nb = 0 ; nb<4;nb++) {
+        if (nb == 0)
+            psTraceSetDestination(stdout);
+        if (nb == 1)
+            psTraceSetDestination(stderr);
+        if (nb == 2)
+            psTraceSetDestination(NULL);
+        if (nb == 3)
+            psTraceSetDestination(fp);
+
+        printPositiveTestHeader(stdout,
+                                "psTrace functions",
+                                "psTrace()");
+
+        (void)psTraceSetLevel(".", 4);
+        psTrace(".", 5, "(0) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".", 7);
+        psTrace(".", 5, "(0) This message should be displayed (%x)\n",
+                0xbeefface);
+
+        (void)psTraceSetLevel(".a", 4);
+        psTrace(".a", 5, "(1) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".a", 7);
+        psTrace(".a", 5, "(1) This message should be displayed (%x)\n",
+                0xbeefface);
+
+
+        (void)psTraceSetLevel(".a.b", 4);
+        psTrace(".a.b", 5, "(2) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".a.b", 7);
+        psTrace(".a.b", 5, "(2) This message should be displayed (%x)\n",
+                0xbeefface);
+
+        printFooter(stdout,
+                    "psTrace functions",
+                    "psTrace()",
+                    true);
+    }
+    fclose(fp);
+
+    return(0);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psTrace03.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psTrace03.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psTrace03.c	(revision 1553)
@@ -0,0 +1,39 @@
+/*****************************************************************************
+    This code will test whether trace messages can be printed successfully
+    with psTracePrintLevels().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    printPositiveTestHeader(stdout,
+                            "psTrace functions",
+                            "psTracePrintLevels()");
+
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel(".a", 8);
+    (void)psTraceSetLevel(".b", 7);
+    (void)psTraceSetLevel(".c", 5);
+
+    (void)psTraceSetLevel(".a.a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+
+    (void)psTraceSetLevel(".b.a", 2);
+    (void)psTraceSetLevel(".b.b", 1);
+
+    (void)psTraceSetLevel(".c.a", 0);
+    (void)psTraceSetLevel(".c.b", 3);
+    (void)psTraceSetLevel(".c.c", 5);
+
+    psTracePrintLevels();
+
+    printFooter(stdout,
+                "psTrace functions",
+                "psTracePrintLevels()",
+                true);
+
+    return(0);
+}
Index: /tags/rel2_1/psLib/test/sysUtils/tst_psTrace04.c
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/tst_psTrace04.c	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/tst_psTrace04.c	(revision 1553)
@@ -0,0 +1,55 @@
+/*****************************************************************************
+    This code will test whether trace messages can be printed successfully
+    with psTracePrintLevels().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib.h"
+#include "psTest.h"
+
+int main()
+{
+    printPositiveTestHeader(stdout,
+                            "psTrace functions",
+                            "Testing psTraceReset()");
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel(".a", 8);
+    (void)psTraceSetLevel(".b", 7);
+    (void)psTraceSetLevel(".c", 5);
+
+    (void)psTraceSetLevel(".a.a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+
+    (void)psTraceSetLevel(".b.a", 2);
+    (void)psTraceSetLevel(".b.b", 1);
+
+    (void)psTraceSetLevel(".c.a", 0);
+    (void)psTraceSetLevel(".c.b", 3);
+    (void)psTraceSetLevel(".c.c", 5);
+
+    psTraceReset();
+
+    if (psTraceGetLevel(".") ||
+            psTraceGetLevel(".a") ||
+            psTraceGetLevel(".b") ||
+            psTraceGetLevel(".c") ||
+            psTraceGetLevel(".a.a") ||
+            psTraceGetLevel(".a.b") ||
+            psTraceGetLevel(".b.a") ||
+            psTraceGetLevel(".b.b") ||
+            psTraceGetLevel(".c.a") ||
+            psTraceGetLevel(".c.b") ||
+            psTraceGetLevel(".c.c")) {
+        printFooter(stdout,
+                    "psTrace functions",
+                    "psTraceReset() did not reset all levels of the tree.",
+                    false);
+        return(1);
+    } else {
+        printFooter(stdout,
+                    "psTrace functions",
+                    "psTraceReset()",
+                    true);
+        return(0);
+    }
+}
Index: /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_01.stderr	(revision 1553)
@@ -0,0 +1,7 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: atst_psAbort_01.c                                          *
+*            TestPoint: psAbort{Multiple type values in abort message}             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|A|           main|ALL TYPES intval = 1 longval = 2 floatval = 3.010000 charval = E strval = E R R O R
Index: /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_02.stderr	(revision 1553)
@@ -0,0 +1,7 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: atst_psAbort_02.c                                          *
+*            TestPoint: psAbort{String values in abort message}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|A|       __LINE__|NO_VALUES
Index: /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/atst_psAbort_03.stderr	(revision 1553)
@@ -0,0 +1,7 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: atst_psAbort_03.c                                          *
+*            TestPoint: psAbort{Empty strings in abort message}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|A|               |
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psError.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psError.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psError.stderr	(revision 1553)
@@ -0,0 +1,30 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psError.c                                              *
+*            TestPoint: psError{Multiple type values in error message}             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|           main|ALL TYPES intval = 1 longval = 2 floatval = 3.010000 charval = E strval = E R R O R
+
+---> TESTPOINT PASSED (psError{Multiple type values in error message} | tst_psError.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psError.c                                              *
+*            TestPoint: psError{String values in error message}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|       __LINE__|NO VALUES
+
+---> TESTPOINT PASSED (psError{String values in error message} | tst_psError.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psError.c                                              *
+*            TestPoint: psError{Empty strings in error message}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|               |
+
+---> TESTPOINT PASSED (psError{Empty strings in error message} | tst_psError.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash00.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash00.c                                             *
+*            TestPoint: psHash functions{psHashAlloc()}                            *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashAlloc()} | tst_psHash00.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash01.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash01.c                                             *
+*            TestPoint: psHash functions{psHashFree()}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashFree()} | tst_psHash01.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash03.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash03.c                                             *
+*            TestPoint: psHash functions{psHashRemove()}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psHash functions{psHashRemove()} | tst_psHash03.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psHash04.stdout	(revision 1553)
@@ -0,0 +1,13 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psHash04.c                                             *
+*            TestPoint: psHash functions{psHashKeyList()}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+Linked List Entries: ENTRY03
+Linked List Entries: ENTRY02
+Linked List Entries: ENTRY01
+Linked List Entries: ENTRY00
+
+---> TESTPOINT PASSED (psHash functions{psHashKeyList()} | tst_psHash04.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stderr	(revision 1553)
@@ -0,0 +1,8 @@
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0 0.000000 beep beep
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1 1.000000 beep beep
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2 2.000000 beep beep
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3 3.000000 beep beep
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0 0.000000 beep beep
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1 1.000000 beep beep
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2 2.000000 beep beep
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3 3.000000 beep beep
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg00.stdout	(revision 1553)
@@ -0,0 +1,18 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psLogMsg00.c                                           *
+*            TestPoint: psLogMsg functions{default log levels, printf-style strings} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psLogMsg functions{default log levels} | tst_psLogMsg00.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psLogMsg00.c                                           *
+*            TestPoint: psLogMsg functions{default log levels, psVLogMsg()}        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psLogMsg functions{default log levels} | tst_psLogMsg00.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stderr	(revision 1553)
@@ -0,0 +1,11 @@
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
+<DATE><TIME>|<HOST>|4|           main|Hello World!  My level is 4
+<DATE><TIME>|<HOST>|5|           main|Hello World!  My level is 5
+<DATE><TIME>|<HOST>|6|           main|Hello World!  My level is 6
+<DATE><TIME>|<HOST>|7|           main|Hello World!  My level is 7
+<DATE><TIME>|<HOST>|8|           main|Hello World!  My level is 8
+<DATE><TIME>|<HOST>|9|           main|Hello World!  My level is 9
+<DATE><TIME>|<HOST>|4|           main|This should  be displayed (level 4)
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg01.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psLogMsg01.c                                           *
+*            TestPoint: psLogMsg functions{psLogSetLevel()}                        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psLogMsg functions{psLogSetLevel()} | tst_psLogMsg01.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg02.stderr	(revision 1553)
@@ -0,0 +1,42 @@
+------------- psLogSetFormat() -------------
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
+------------- psLogSetFormat(NULL) -------------
+------------- psLogSetFormat(T) -------------
+<DATE><TIME>|
+<DATE><TIME>|
+<DATE><TIME>|
+<DATE><TIME>|
+------------- psLogSetFormat(H) -------------
+<HOST>|
+<HOST>|
+<HOST>|
+<HOST>|
+------------- psLogSetFormat(L) -------------
+A|
+E|
+W|
+I|
+------------- psLogSetFormat(N) -------------
+           main|
+           main|
+           main|
+           main|
+------------- psLogSetFormat(M) -------------
+Hello World!  My level is 0
+Hello World!  My level is 1
+Hello World!  My level is 2
+Hello World!  My level is 3
+------------- psLogSetFormat(THLNM) -------------
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
+<DATE><TIME>|<HOST>|A| Under 15 chars|Hello World!
+<DATE><TIME>|<HOST>|A|This string is |Hello World!
+<DATE><TIME>|<HOST>|A|           main|Line #1
+<DATE><TIME>|<HOST>|A|           main|Line #2
+<DATE><TIME>|<HOST>|A|           main|Line #3
+<DATE><TIME>|<HOST>|A|           main|Line #4
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stderr	(revision 1553)
@@ -0,0 +1,4 @@
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psLogMsg03.stdout	(revision 1553)
@@ -0,0 +1,23 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psLogMsg03.c                                           *
+*            TestPoint: psLogMsg functions{psLogSetDestination()}                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+--------------- psLogSetDestination(PS_LOG_NONE) ----------------
+------------- psLogSetDestination(PS_LOG_TO_STDERR) -------------
+------------- psLogSetDestination(PS_LOG_TO_STDOUT) -------------
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
+--------------- psLogSetDestination(file:log.txt) ---------------
+--------------------- The Contents of log.txt -------------------
+<DATE><TIME>|<HOST>|A|           main|Hello World!  My level is 0
+<DATE><TIME>|<HOST>|E|           main|Hello World!  My level is 1
+<DATE><TIME>|<HOST>|W|           main|Hello World!  My level is 2
+<DATE><TIME>|<HOST>|I|           main|Hello World!  My level is 3
+--------------- psLogSetDestination(file:/eva/log.txt) ----------
+
+---> TESTPOINT PASSED (psLogMsg functions{psLogSetDestination()} | tst_psLogMsg03.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psMemory.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psMemory.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psMemory.stderr	(revision 1553)
@@ -0,0 +1,121 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{checkBufferPositive}                              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|TPCheckBufferPo|psAlloc shall allocate memory blocks writeable by caller.
+
+---> TESTPOINT PASSED (psMemory{checkBufferPositive} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{outOfMemory}                                      *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|  TPOutOfMemory|Upon requesting more memory than is available, psalloc shall call the psMemExhaustedCallback.
+<DATE><TIME>|<HOST>|I|TPOutOfMemoryEx|Custom MemExhaustedCallback was invoked.
+<DATE><TIME>|<HOST>|A|      p_psAlloc|Failed to allocate <N> bytes at tst_psMemory.c:<LINENO>
+
+---> TESTPOINT PASSED (psMemory{outOfMemory} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{reallocOutOfMemory}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|TPReallocOutOfM|Upon requesting more memory than is available, psRealloc shall call the psMemExhaustedCallback.
+<DATE><TIME>|<HOST>|A|    p_psRealloc|Failed to reallocate <N> bytes at tst_psMemory.c:<LINENO>
+
+---> TESTPOINT PASSED (psMemory{reallocOutOfMemory} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{psRealloc}                                        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|      TPrealloc|psRealloc shall increase/decrease memory buffer while preserving contents
+<DATE><TIME>|<HOST>|I|      TPrealloc|Expanding memory buffer.
+<DATE><TIME>|<HOST>|I|      TPrealloc|Shrinking memory buffer.
+
+---> TESTPOINT PASSED (psMemory{psRealloc} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{allocCallback}                                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|TPallocCallback|call to psAlloc/psRealloc shall generate a callback if specified memory ID is allocated.
+<DATE><TIME>|<HOST>|I|memAllocateCall|block 2 was (re)allocated
+<DATE><TIME>|<HOST>|I|memAllocateCall|block 3 was (re)allocated
+<DATE><TIME>|<HOST>|I|memFreeCallback|block 2 was freed
+<DATE><TIME>|<HOST>|I|memFreeCallback|block 3 was freed
+<DATE><TIME>|<HOST>|I|memAllocateCall|block 4 was (re)allocated
+<DATE><TIME>|<HOST>|I|memAllocateCall|block 4 was (re)allocated
+<DATE><TIME>|<HOST>|I|memFreeCallback|block 4 was freed
+
+---> TESTPOINT PASSED (psMemory{allocCallback} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{checkLeaks}                                       *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|psMemCheckLeaks shall return the number of blocks above an ID that are still allocated
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|following psMemCheckLeaks call should produce one instance.
+                   file:line ID
+         tst_psMemory.c:<LINENO>  1
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|Testing psMemCheckLeaks again with a different leak location
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|following psMemCheckLeaks call should produce one error.
+                   file:line ID
+         tst_psMemory.c:<LINENO>  11
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|Testing psMemCheckLeaks again with multiple leak locations.
+<DATE><TIME>|<HOST>|I|   TPcheckLeaks|following psMemCheckLeaks call should produce two errors.
+                   file:line ID
+         tst_psMemory.c:<LINENO>  16
+         tst_psMemory.c:<LINENO>  14
+
+---> TESTPOINT PASSED (psMemory{checkLeaks} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{psMemCorruption}                                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|TPmemCorruption|psMemCheckCorruption shall detect memory corruptions
+<DATE><TIME>|<HOST>|I|TPmemCorruption|psMemCheckCorruption should output an error message and memProblemCallback callback should be called.
+<DATE><TIME>|<HOST>|E|psMemCheckCorru|Memory Corruption: memory block 1 is corrupted (buffer underflow)
+<DATE><TIME>|<HOST>|I|memProblemCallb|memory callback called for id 1 (psMemCheckCorruption:<LINENO>).
+
+---> TESTPOINT PASSED (psMemory{psMemCorruption} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{freeReferencedMemory}                             *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I|TPFreeReference|memory reference count shall be incrementable/decrementable
+<DATE><TIME>|<HOST>|I|TPFreeReference|psFree shall be just decrement a multiple refererenced pointer.
+
+---> TESTPOINT PASSED (psMemory{freeReferencedMemory} | tst_psMemory.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psMemory.c                                             *
+*            TestPoint: psMemory{multipleFree}                                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|I| TPmultipleFree|Next should be an error about multiple freeing.
+<DATE><TIME>|<HOST>|E|  checkMemBlock|Memory Corruption: memory block 1 was freed but still used.
+<DATE><TIME>|<HOST>|E|memProblemCallb|Block 1 allocated at tst_psMemory.c:<LINENO> freed more than once at tst_psMemory.c:<LINENO>
+<DATE><TIME>|<HOST>|A|memProblemCallb|Detected a problem in the memory system at tst_psMemory.c:<LINENO>
+
+---> TESTPOINT PASSED (psMemory{multipleFree} | tst_psMemory.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psStringCopy.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psStringCopy.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psStringCopy.stderr	(revision 1553)
@@ -0,0 +1,64 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringCopy{Verify string copy}                           *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStringCopy{Verify string copy} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringCopy{Verify empty string copy}                     *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStringCopy{Verify empty string copy} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringNCopy{Verify string copy with length}              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStringNCopy{Verify string copy with length} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringNCopy{Verify empty string copy with length}        *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStringNCopy{Verify empty string copy with length} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringNCopy{Copy string to larger string}                *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psStringNCopy{Copy string to larger string} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: psStringNCopy{Copy string with negative size}              *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|     psString.c|psStringNCopy with negative count specified -5
+
+---> TESTPOINT PASSED (psStringNCopy{Copy string with negative size} | tst_psStringCopy.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psStringCopy.c                                         *
+*            TestPoint: PS_STRING{Verify creation of string literal}               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (PS_STRING{Verify creation of string literal} | tst_psStringCopy.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace00.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace00.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace00.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace00.c                                            *
+*            TestPoint: psTrace functions{psTraceSetLevel() and psTraceGetLevel()} *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTrace functions{Testing psTraceSetLevel and psTraceGetLevel} | tst_psTrace00.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace01.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace01.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace01.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace01.c                                            *
+*            TestPoint: psTrace functions{psTraceReset()}                          *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTrace functions{psTraceReset()} | tst_psTrace01.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stderr
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stderr	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stderr	(revision 1553)
@@ -0,0 +1,3 @@
+     (0) This message should be displayed (beefface)
+     (1) This message should be displayed (beefface)
+     (2) This message should be displayed (beefface)
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace02.stdout	(revision 1553)
@@ -0,0 +1,42 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace02.c                                            *
+*            TestPoint: psTrace functions{psTrace()}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+     (0) This message should be displayed (beefface)
+     (1) This message should be displayed (beefface)
+     (2) This message should be displayed (beefface)
+
+---> TESTPOINT PASSED (psTrace functions{psTrace()} | tst_psTrace02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace02.c                                            *
+*            TestPoint: psTrace functions{psTrace()}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTrace functions{psTrace()} | tst_psTrace02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace02.c                                            *
+*            TestPoint: psTrace functions{psTrace()}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+     (0) This message should be displayed (beefface)
+     (1) This message should be displayed (beefface)
+     (2) This message should be displayed (beefface)
+
+---> TESTPOINT PASSED (psTrace functions{psTrace()} | tst_psTrace02.c)
+
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace02.c                                            *
+*            TestPoint: psTrace functions{psTrace()}                               *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTrace functions{psTrace()} | tst_psTrace02.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace03.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace03.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace03.stdout	(revision 1553)
@@ -0,0 +1,20 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace03.c                                            *
+*            TestPoint: psTrace functions{psTracePrintLevels()}                    *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+.                    9
+ a                   8
+  a                  4
+  b                  3
+ b                   7
+  a                  2
+  b                  1
+ c                   5
+  a                  0
+  b                  3
+  c                  5
+
+---> TESTPOINT PASSED (psTrace functions{psTracePrintLevels()} | tst_psTrace03.c)
+
Index: /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace04.stdout
===================================================================
--- /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace04.stdout	(revision 1553)
+++ /tags/rel2_1/psLib/test/sysUtils/verified/tst_psTrace04.stdout	(revision 1553)
@@ -0,0 +1,9 @@
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psTrace04.c                                            *
+*            TestPoint: psTrace functions{Testing psTraceReset()}                  *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+
+---> TESTPOINT PASSED (psTrace functions{psTraceReset()} | tst_psTrace04.c)
+
