Index: Makefile
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Makefile,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- Makefile	8 Jan 2004 22:39:38 -0000	1.27
+++ Makefile	8 Sep 2004 19:21:28 -0000	1.28
@@ -7,6 +7,6 @@
 	@echo Nothing to be done here.
 
 dox docs doc:
-	docs/builddocs --update --tree --search --detailed
+	docs/builddocs --all --update --tree --search --detailed
 
 .PHONY: all update install dox docs doc
\ No newline at end of file
Index: README
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/README,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- README	21 Jan 2004 05:37:34 -0000	1.6
+++ README	1 Apr 2004 00:16:51 -0000	1.7
@@ -1,7 +1,7 @@
 Welcome to the Tekkotsu framework.
 Unless otherwise noted, all source code and related files are
-Copyright 2003, Carnegie Mellon University AIBO Lab
-Released under the GPL.
+Copyright 2004, Carnegie Mellon University AIBO Lab
+Released under the LGPL.
 
 Documentation and Usage Guides:
 ------------------------------
Index: entry.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/entry.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- entry.h	25 Jul 2003 20:18:00 -0000	1.1
+++ entry.h	17 Jul 2004 03:38:01 -0000	1.2
@@ -2,3 +2,4 @@
 // OPEN_R_SDK/OPEN_R/include/OPENR/core_macro.h:10
 // which says  #include "entry.h" (a stub-generated file, specific to each process)
 
+
Index: license.txt
===================================================================
RCS file: license.txt
diff -N license.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ license.txt	1 Apr 2004 00:16:51 -0000	1.1
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Index: Behaviors/BehaviorBase.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/BehaviorBase.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- Behaviors/BehaviorBase.h	9 Feb 2004 22:45:28 -0000	1.13
+++ Behaviors/BehaviorBase.h	24 Mar 2004 06:38:21 -0000	1.14
@@ -7,8 +7,20 @@
 #include <string>
 
 //! The basis from which all other Behaviors should inherit
-/*! Makes use of ReferenceCounter so that behaviors can automatically delete themselves if wanted\n
- *  Make sure your own DoStart and DoStop call BehaviorBase::DoStart (or Stop) to allow this behavior... otherwise you'll get memory leaks */
+/*! Makes use of ReferenceCounter so that behaviors can automatically delete themselves if
+ *  wanted.
+ *
+ *  Make sure your own DoStart and DoStop call BehaviorBase::DoStart (or Stop) to allow
+ *  the auto-deletion from reference counting... otherwise you'll get memory leaks if you
+ *  rely on the reference counting.
+ *
+ *  For an empty behavior boilerplate file to help you get started quickly, try
+ *  <a href="http://cvs.tekkotsu.org/cgi-bin/viewcvs.cgi/Tekkotsu/docs/behavior_header.h?rev=HEAD&content-type=text/vnd.viewcvs-markup"><i>Tekkotsu</i><tt>/docs/behavior_header.h</tt></a>:
+ * 
+ *  But it would probably still be a good idea to go through the "<a
+ *  href="../FirstBehavior.html">First Behavior</a>" tutorial to get a better idea of
+ *  what's going on.
+ */
 class BehaviorBase : public ReferenceCounter, public EventListener {
  public:
 	//! constructor
@@ -80,9 +92,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.13 $
+ * $Revision: 1.14 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/03/24 06:38:21 $
  */
 
 #endif
Index: Behaviors/Controller.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controller.cc,v
retrieving revision 1.36
retrieving revision 1.40
diff -u -d -r1.36 -r1.40
--- Behaviors/Controller.cc	1 Mar 2004 21:16:48 -0000	1.36
+++ Behaviors/Controller.cc	17 Oct 2004 01:16:10 -0000	1.40
@@ -43,7 +43,7 @@
 	SharedObject<LedMC> leds;
 	leds->setWeights(~FaceLEDMask,0);
 	leds->setWeights(FaceLEDMask,.75);
-	display=motman->addMotion(leds,isControlling?MotionManager::kEmergencyPriority:MotionManager::kIgnoredPriority);
+	display=motman->addPersistentMotion(leds,isControlling?MotionManager::kEmergencyPriority:MotionManager::kIgnoredPriority);
 	reset();
 }
 
@@ -58,7 +58,7 @@
 	sndman->ReleaseFile(config->controller.prev_snd);
 	sndman->ReleaseFile(config->controller.read_snd);
 	sndman->ReleaseFile(config->controller.cancel_snd);
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	reset();
 	gui_comm->printf("goodbye\n");
 	wireless->setDaemon(gui_comm,false);
@@ -453,7 +453,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.36 $
+ * $Revision: 1.40 $
  * $State: Exp $
- * $Date: 2004/03/01 21:16:48 $
+ * $Date: 2004/10/17 01:16:10 $
  */
Index: Behaviors/Controller.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controller.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- Behaviors/Controller.h	9 Feb 2004 22:45:28 -0000	1.28
+++ Behaviors/Controller.h	24 Mar 2004 05:35:00 -0000	1.29
@@ -25,10 +25,11 @@
  *	- '<tt>!cancel</tt>' - calls ControlBase::doCancel() of the current control
  *	- '<tt>!msg </tt><i>text</i>' - sends <i>text</i> out as a TextMsgEvent; also note that any text entered on the console port while a GUI is also connected will also be sent as a TextMsgEvent, without needing the !input.
  *  - '<tt>!root </tt><i>text</i>' - calls ControlBase::takeInput(<i>text</i>) on the root control
- *  - '<tt>!hello</tt>' - responds with '<tt>hello\n</tt><i>count</i>' where <i>count</i> is the number of times '<tt>!hello</tt>' has been sent.  Good for detecting first connection after boot vs. a reconnect.
+ *  - '<tt>!hello</tt>' - responds with '<tt>hello\\n</tt><i>count</i>\\n' where <i>count</i> is the number of times '<tt>!hello</tt>' has been sent.  Good for detecting first connection after boot vs. a reconnect.
  *	- '<tt>!hilight</tt> [<i>n1</i> [<i>n2</i> [...]]]' - hilights zero, one, or more items in the menu
  *	- '<tt>!input </tt><i>text</i>' - calls ControlBase::takeInput(text) on the currently hilighted control(s)
- *	- any text not beginning with '!' - sent to ControlBase::takeInput() of the current control
+ *  - '<tt>!set </tt><i>section</i><tt>.</tt><i>key</i><tt>=</tt><i>value</i>' - will be sent to Config::setValue(<i>section</i>,<i>key</i>,<i>value</i>)
+ *	- any text not beginning with '<tt>!</tt>' - sent to ControlBase::takeInput() of the current control
  *
  *  In return, to send the menus to the GUI, the following messages are sent: (newlines are required where shown)
  *  - '<tt>push</tt>' - signals a submenu has been activated
@@ -211,9 +212,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.28 $
+ * $Revision: 1.29 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/03/24 05:35:00 $
  */
 
 #endif
Index: Behaviors/StateNode.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/StateNode.cc,v
retrieving revision 1.13
retrieving revision 1.17
diff -u -d -r1.13 -r1.17
--- Behaviors/StateNode.cc	11 Nov 2003 00:08:09 -0000	1.13
+++ Behaviors/StateNode.cc	4 Oct 2004 22:57:56 -0000	1.17
@@ -18,6 +18,14 @@
 	trans->addSource(this);
 }
 
+StateNode* StateNode::addNode(StateNode* node) {
+  nodes.push_back(node);
+  node->AddReference();
+  if ( node->parent == NULL )
+    node->parent = this;
+  return node;
+}
+
 void StateNode::DoStart() {
 	BehaviorBase::DoStart();
 	if(!issetup) {
@@ -25,7 +33,7 @@
 		issetup=true;
 	}
 	for(std::vector<Transition*>::iterator it=transitions.begin(); it!=transitions.end(); it++)
-		(*it)->DoStart();
+	  if ( !(*it)->isActive()  ) (*it)->DoStart();
 	erouter->postEvent(EventBase::stateMachineEGID,reinterpret_cast<unsigned int>(this),EventBase::activateETID,0,getName(),1);
 	if(parent!=NULL)
 		parent->transitionTo(this);
@@ -33,7 +41,6 @@
 
 void StateNode::DoStop() {
 	for(std::vector<Transition*>::iterator it=transitions.begin(); it!=transitions.end(); it++) {
-		ASSERT((*it)->isActive(),"Inactive transition");
 		if((*it)->isActive())
 			(*it)->DoStop();
 	}
@@ -67,10 +74,10 @@
  * @brief Describes StateNode, which is both a state machine controller as well as a node within a state machine itself
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.13 $
+ * $Revision: 1.17 $
  * $State: Exp $
- * $Date: 2003/11/11 00:08:09 $
+ * $Date: 2004/10/04 22:57:56 $
  */
 
Index: Behaviors/StateNode.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/StateNode.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Behaviors/StateNode.h	30 Oct 2003 23:23:15 -0000	1.9
+++ Behaviors/StateNode.h	4 Oct 2004 22:57:56 -0000	1.10
@@ -28,8 +28,8 @@
 	//!Returns the std::vector of transitions so you can modify them yourself if need be
 	std::vector<Transition*>& getTransitions() { return transitions; }
 
-	//!Adds a StateNode to #nodes so it can be automatically dereferenced later, returns what it's passed (for convenience), calls AddReference() on @a node
-	virtual StateNode* addNode(StateNode* node) { nodes.push_back(node); node->AddReference(); return node; }
+	//!Adds a StateNode to #nodes so it can be automatically dereferenced later, returns what it's passed (for convenience), calls AddReference() on @a node.  Also sets the node's parent to #this if it is null.
+	virtual StateNode* addNode(StateNode* node);
 
 	//!Returns the std::vector of nodes so you can modify them yourself if need be
 	std::vector<StateNode*>& getNodes() { return nodes; }
@@ -92,11 +92,11 @@
  * @brief Describes StateNode, which is both a state machine controller as well as a node within a state machine itself
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.10 $
  * $State: Exp $
- * $Date: 2003/10/30 23:23:15 $
+ * $Date: 2004/10/04 22:57:56 $
  */
 
 #endif
Index: Behaviors/Transition.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transition.cc,v
retrieving revision 1.6
retrieving revision 1.8
diff -u -d -r1.6 -r1.8
--- Behaviors/Transition.cc	11 Nov 2003 00:08:10 -0000	1.6
+++ Behaviors/Transition.cc	8 Oct 2004 00:08:34 -0000	1.8
@@ -3,13 +3,13 @@
 #include "Wireless/Wireless.h"
 #include "SoundPlay/SoundManager.h"
 
-void Transition::activate() {
-	//serr->printf("%s activate() - enter %d\n",getName().c_str(),get_time());
+void Transition::fire() {
+	//serr->printf("%s fire() - enter %d\n",getName().c_str(),get_time());
 
 	AddReference(); //just in case a side effect of this transition is to dereference the transition, we don't want to be deleted while still transitioning
 
 	if(sound.size()!=0)
-		sndman->PlayFile(sound.c_str());
+		sndman->PlayFile(sound);
 
 	for(unsigned int i=0; i<srcs.size(); i++)
 		if(srcs[i]->isActive()) //It's usually a bad idea to call DoStop/DoStart when it's already stopped/started...
@@ -18,7 +18,7 @@
 		if(!dsts[i]->isActive())
 			dsts[i]->DoStart();
 
-	//serr->printf("%s activate() - leave %d\n",getName().c_str(),get_time());
+	//serr->printf("%s fire() - leave %d\n",getName().c_str(),get_time());
 	RemoveReference();
 }
 
@@ -26,10 +26,10 @@
  * @brief Implements Transition, represents a transition between StateNodes.
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2003/11/11 00:08:10 $
+ * $Date: 2004/10/08 00:08:34 $
  */
 
Index: Behaviors/Transition.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transition.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Behaviors/Transition.h	11 Nov 2003 00:08:10 -0000	1.4
+++ Behaviors/Transition.h	4 Oct 2004 22:59:57 -0000	1.5
@@ -3,6 +3,7 @@
 #define INCLUDED_Transition_h_
 
 #include "BehaviorBase.h"
+#include "Wireless/Socket.h"
 #include <vector>
 
 class StateNode;
@@ -12,7 +13,7 @@
  *  conditions on the transitions.  Transitions are "smart" - they are
  *  behaviors in and of themselves and can listen for events and use
  *  the standard DoStart/DoStop interface.  Based on the events they
- *  receive, they can activate() themselves and cause a state
+ *  receive, they can fire() themselves and cause a state
  *  transition.
  *
  *  DoStart() will be called when this transition is 'active' - it
@@ -20,10 +21,10 @@
  *  DoStop() is called.
  *  
  *  If the conditions are satisified for a transition, you should call
- *  activate() to do the appropriate notifications.
+ *  fire() to do the appropriate notifications.
  *
  *  Also note that a transition can have multiple sources and
- *  destinations.  See activate().
+ *  destinations.  See fire().
  *
  *  When setting up, the flow of additions follows the flow of
  *  control.  In other words, you add a transition to a source, and
@@ -51,7 +52,13 @@
 	virtual ~Transition() {}
 
 	//!call this when the transition should be made, base class version simply calls StateNode::DoStop() on each active of #srcs and StateNode::DoStart() on each inactive of #dsts, but you can override.
-	virtual void activate();
+	virtual void fire();
+
+  //!deprecated: use #fire() instead
+  virtual void activate() {
+    serr->printf("Transition::activate() is deprecated.  Use Transition::fire() instead.\n");
+    fire();
+  }
 
 	virtual std::vector<StateNode*>& getSources() { return srcs; }  //!< returns a user-modifiable reference to the current source list
 	virtual const std::vector<StateNode*>& getSources() const { return srcs; } //!< returns a const reference to the current source list
@@ -78,11 +85,11 @@
  * @brief Describes Transition, represents a transition between StateNodes.
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2003/11/11 00:08:10 $
+ * $Date: 2004/10/04 22:59:57 $
  */
 
 #endif
Index: Behaviors/Controls/BatteryCheckControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/BatteryCheckControl.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- Behaviors/Controls/BatteryCheckControl.h	19 Jan 2004 20:34:51 -0000	1.8
+++ Behaviors/Controls/BatteryCheckControl.h	7 Oct 2004 19:07:04 -0000	1.9
@@ -41,7 +41,7 @@
 	}
 	//! stops listening for power events and sets display to invalid
 	virtual void pause() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		display_id=MotionManager::invalid_MC_ID;
 	}
 	//! calls report()
@@ -63,7 +63,7 @@
 	}
 	//! stops listening for power events and sets display to invalid
 	virtual void deactivate() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		display_id=MotionManager::invalid_MC_ID;
 	}
 	//! calls refresh() to redisplay with new information if it's not a vibration event
@@ -112,9 +112,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2004/01/19 20:34:51 $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
 #endif
Index: Behaviors/Controls/ControlBase.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/ControlBase.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- Behaviors/Controls/ControlBase.h	18 Feb 2004 21:11:25 -0000	1.20
+++ Behaviors/Controls/ControlBase.h	7 Oct 2004 22:15:37 -0000	1.21
@@ -123,12 +123,12 @@
 	virtual ControlBase& setDescription(const std::string d) { description=d; return *this; } //!< sets the description of the control
 	virtual std::string getDescription() const { return description; } //!< returns a short description of what the control does
 
-	const std::vector<ControlBase*>& getSlots() const { return options; } //!< returns the vector of sub-controls
-	std::string getSlotName(unsigned int i) const; //!< returns the string that will appear in slot @a i
-	unsigned int slotsSize() const { return options.size(); } //!< returns the number of options available
-	void setSlot(unsigned int i,ControlBase* o); //!< sets @a i'th element of #options to @a o
-	void pushSlot(ControlBase* o); //!< sets next unused element of #options to @a o
-	void clearSlots(); //!< deletes each slot item and clears the slots
+	virtual const std::vector<ControlBase*>& getSlots() const { return options; } //!< returns the vector of sub-controls
+	virtual std::string getSlotName(unsigned int i) const; //!< returns the string that will appear in slot @a i
+	virtual unsigned int slotsSize() const { return options.size(); } //!< returns the number of options available
+	virtual void setSlot(unsigned int i,ControlBase* o); //!< sets @a i'th element of #options to @a o
+	virtual void pushSlot(ControlBase* o); //!< sets next unused element of #options to @a o
+	virtual void clearSlots(); //!< deletes each slot item and clears the slots
 
 	virtual const std::vector<unsigned int>& getHilights() const { return hilights; } //!< returns a vector of the indicies of hilighted slots
 	virtual void setHilights(const std::vector<unsigned int>& hi); //!< sets the hilighted slots
@@ -169,8 +169,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.20 $
+ * $Revision: 1.21 $
  * $State: Exp $
- * $Date: 2004/02/18 21:11:25 $
+ * $Date: 2004/10/07 22:15:37 $
  */
 #endif
Index: Behaviors/Controls/EventLogger.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/EventLogger.cc,v
retrieving revision 1.11
retrieving revision 1.13
diff -u -d -r1.11 -r1.13
--- Behaviors/Controls/EventLogger.cc	9 Jan 2004 04:38:52 -0000	1.11
+++ Behaviors/Controls/EventLogger.cc	7 Oct 2004 22:15:21 -0000	1.13
@@ -63,36 +63,17 @@
 
 //!sends all events received to stdout and/or logfile
 void EventLogger::processEvent(const EventBase& event) {
-	std::ostringstream logdata;
-	logdata << event.getName();
-	switch(event.getTypeID()) {
-	case EventBase::activateETID:
-		logdata << "\tA"; break;
-	case EventBase::statusETID:
-		logdata << "\tS"; break;
-	case EventBase::deactivateETID:
-		logdata << "\tD"; break;
-	case EventBase::numETIDs:
-		logdata << "\tErr"; break;
-	}
-	if(verbosity>=1)
-		logdata << '\t' << event.getDuration() << '\t' << event.getTimeStamp();
-	if(verbosity>=2)
-		logdata << '\t' << event.getMagnitude();
-	if(verbosity>=3) {
-		if(const LocomotionEvent * loco=dynamic_cast<const LocomotionEvent*>(&event))
-			logdata << '\t' << loco->x << '\t' << loco->y << '\t' << loco->a;
-		if(const TextMsgEvent * text=dynamic_cast<const TextMsgEvent*>(&event))
-			logdata << '\t' << text->getToken() << '\t' << text->getText();
-		if(const VisionObjectEvent * vis=dynamic_cast<const VisionObjectEvent*>(&event))
-			logdata << '\t' << vis->getCenterX() << '\t' << vis->getCenterY() << '\t' << vis->getDistance();
-	}
-	
+	std::string logdata = event.getDescription(true,verbosity);
 	if(options[EventBase::numEGIDs+2]->getName()[1]=='X')
-		sout->printf("EVENT: %s\n",logdata.str().c_str());
+		sout->printf("EVENT: %s\n",logdata.c_str());
 	checkLogFile();
 	if(logfile)
-		logfile << logdata.str() << endl;
+		logfile << logdata << endl;
+}
+
+void EventLogger::clearSlots() {
+	erouter->removeListener(this);
+	ControlBase::clearSlots();
 }
 
 void EventLogger::setStatus(unsigned int i, char c) {
@@ -128,7 +109,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.11 $
+ * $Revision: 1.13 $
  * $State: Exp $
- * $Date: 2004/01/09 04:38:52 $
+ * $Date: 2004/10/07 22:15:21 $
  */
Index: Behaviors/Controls/EventLogger.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/EventLogger.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Behaviors/Controls/EventLogger.h	25 Sep 2003 15:26:10 -0000	1.5
+++ Behaviors/Controls/EventLogger.h	7 Oct 2004 22:15:20 -0000	1.6
@@ -11,6 +11,7 @@
 public:
 	//!constructor
 	EventLogger();
+	virtual ~EventLogger() { clearSlots(); }
 
 	//!opens a custom (embedded) menu to toggle individual EGIDs
 	virtual ControlBase* doSelect();
@@ -21,6 +22,8 @@
 	virtual void processEvent(const EventBase& event);
 
 protected:
+	virtual void clearSlots();
+
 	//!sets the status char of slot @a i to @a c
 	void setStatus(unsigned int i, char c);
 
@@ -43,9 +46,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
- * $State: Rel $
- * $Date: 2003/09/25 15:26:10 $
+ * $Revision: 1.6 $
+ * $State: Exp $
+ * $Date: 2004/10/07 22:15:20 $
  */
 
 #endif
Index: Behaviors/Controls/FileInputControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/FileInputControl.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Behaviors/Controls/FileInputControl.h	8 Jan 2004 22:39:54 -0000	1.1
+++ Behaviors/Controls/FileInputControl.h	23 Mar 2004 00:55:01 -0000	1.2
@@ -19,10 +19,13 @@
 	{}
 
 	//! returns the path to file last selected
-	const std::string& getLastInput() { return myfile; }
+	virtual const std::string& getLastInput() { return myfile; }
+
+	//! clears the last input (i.e. so you can easily tell later if new input is entered)
+	virtual void clearLastInput() { selectedFile(""); }
 
 	//! pass pointer to an external string you wish to have set when a file is selected; NULL otherwise
-	void setStore(std::string* store) { file=store; }
+	virtual void setStore(std::string* store) { file=store; }
 	
 protected:
 	virtual ControlBase* selectedFile(const std::string& f) {
@@ -46,9 +49,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * $State: Exp $
- * $Date: 2004/01/08 22:39:54 $
+ * $Date: 2004/03/23 00:55:01 $
  */
 
 #endif
Index: Behaviors/Controls/FreeMemReportControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/FreeMemReportControl.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Behaviors/Controls/FreeMemReportControl.h	26 Sep 2003 03:28:38 -0000	1.6
+++ Behaviors/Controls/FreeMemReportControl.h	7 Oct 2004 19:07:04 -0000	1.7
@@ -26,7 +26,7 @@
 
 	virtual void DoStop() {
 		isWarning=false;
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		BehaviorBase::DoStop();
 	}
 
@@ -67,9 +67,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
- * $State: Rel $
- * $Date: 2003/09/26 03:28:38 $
+ * $Revision: 1.7 $
+ * $State: Exp $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
 #endif
Index: Behaviors/Controls/HelpControl.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/HelpControl.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Behaviors/Controls/HelpControl.cc	21 Jan 2004 20:18:49 -0000	1.6
+++ Behaviors/Controls/HelpControl.cc	14 Jul 2004 00:50:26 -0000	1.7
@@ -1,5 +1,7 @@
 #include "HelpControl.h"
 
+//#define HelpControl_HTML_
+
 ControlBase * HelpControl::activate(MotionManager::MC_ID disp_id, Socket * gui) {
 	char * fmt="  * ";
 	if(config->main.use_VT100) {
@@ -33,7 +35,9 @@
 	unsigned int numlen=1;
 	if(slots.size()>1)
 		numlen=(int)(log(slots.size()-1)/log(10))+1;
-	//sout->printf("<ol>\n");
+#ifdef HelpControl_HTML_
+	sout->printf("<ol>\n");
+#endif
 	for(unsigned int i=0; i<slots.size(); i++) {
 		if(slots[i]==NULL)
 			continue;
@@ -47,11 +51,14 @@
 			len=desc.size();
 		else
 			while(len>0 && !isspace(desc[len-1])) len--;
+#ifdef HelpControl_HTML_
+		fmt="%s<li><!--%*d--><code><b>%s</b>: %s";
+#else
 		if(config->main.use_VT100)
 			fmt="\33[1m%s%*d. %s\33[0m: %s\n";
 		else
 			fmt="%s%*d. %s: %s\n";
-		//fmt="%s<li><!--%*d--><code><b>%s</b>: %s";
+#endif
 		sout->printf(fmt,prefix.c_str(),numlen,i,nm.c_str(),desc.substr(0,len).c_str());
 		while(len<desc.size() && isspace(desc[len])) len++;
 		desc=desc.substr(len);
@@ -68,15 +75,22 @@
 				if(len>desc.size())
 					len=desc.size();
 			}
-			//sout->printf("\n%s",desc.substr(0,len).c_str());
+#ifdef HelpControl_HTML_
+			sout->printf("\n%s",desc.substr(0,len).c_str());
+#else
 			sout->printf("%s%s\n",std::string(prefix.size(),' ').c_str(),desc.substr(0,len).c_str());
+#endif
 			while(len<desc.size() && isspace(desc[len])) len++;
 			desc=desc.substr(len);
 		}
-		//sout->printf("</code></li>\n");
+#ifdef HelpControl_HTML_
+		sout->printf("</code></li>\n");
+#endif
 		report(slots[i],pre,depth_remain-1);
 	}
-	//sout->printf("</ol>\n");
+#ifdef HelpControl_HTML_
+	sout->printf("</ol>\n");
+#endif
 }
 
 /*! @file
@@ -85,8 +99,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2004/01/21 20:18:49 $
+ * $Date: 2004/07/14 00:50:26 $
  */
 
Index: Behaviors/Controls/LoadPostureControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/LoadPostureControl.h,v
retrieving revision 1.10
retrieving revision 1.13
diff -u -d -r1.10 -r1.13
--- Behaviors/Controls/LoadPostureControl.h	26 Jul 2003 01:48:03 -0000	1.10
+++ Behaviors/Controls/LoadPostureControl.h	17 Oct 2004 01:16:10 -0000	1.13
@@ -36,7 +36,7 @@
 	}
 	
 	virtual void deactivate() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 	}
 
 protected:
@@ -46,7 +46,7 @@
 		SharedObject<PostureMC> post;
 		post->LoadFile(file.c_str());
 		MMAccessor<EmergencyStopMC>(estopid)->setActive(false);
-		MotionManager::MC_ID id=motman->addMotion(post,MotionManager::kEmergencyPriority+1,true);
+		MotionManager::MC_ID id=motman->addPrunableMotion(post,MotionManager::kEmergencyPriority+1);
 		erouter->addListener(this,EventBase::motmanEGID,id,EventBase::deactivateETID);
 		return this;
 	}
@@ -61,9 +61,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
- * $State: Rel $
- * $Date: 2003/07/26 01:48:03 $
+ * $Revision: 1.13 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Controls/PostureEditor.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/PostureEditor.cc,v
retrieving revision 1.3
retrieving revision 1.7
diff -u -d -r1.3 -r1.7
--- Behaviors/Controls/PostureEditor.cc	30 Jan 2004 01:48:02 -0000	1.3
+++ Behaviors/Controls/PostureEditor.cc	18 Oct 2004 19:53:02 -0000	1.7
@@ -1,11 +1,19 @@
 #include "PostureEditor.h"
 #include "Motion/MMAccessor.h"
+#include "Motion/EmergencyStopMC.h"
+#include "Motion/MotionSequenceMC.h"
+#include "Motion/LedMC.h"
+#include "Events/EventRouter.h"
 #include "ValueEditControl.h"
 #include "NullControl.h"
+#include "SoundPlay/SoundManager.h"
 
-PostureEditor::PostureEditor()
+typedef MotionSequenceMC<MotionSequence::SizeSmall> reach_t; //!< just to save some typing
+
+PostureEditor::PostureEditor(MotionManager::MC_ID estop_ID)
 	: ControlBase("Posture Editor","Allows you to load, save, and numerically edit the posture"), 
-		poseMC(), poseID(MotionManager::invalid_MC_ID), lastSlot(NULL), loadPose(NULL), savePose(NULL)
+	  pose(), reachID(MotionManager::invalid_MC_ID),
+	  estopID(estop_ID), lastSlot(NULL), loadPose(NULL), savePose(NULL), pauseCalled(false)
 {
 	// add load and save menus
 	pushSlot(loadPose=new FileInputControl("Load Posture","Select a posture to open",config->motion.root));
@@ -15,51 +23,71 @@
 	// add submenu for weight editors
 	ControlBase * weights;
 	pushSlot(weights=new ControlBase("Weights","Set the weights for outputs"));
-	for(unsigned int i=0; i<NumOutputs; i++) {
-		std::string tmp(outputNames[i]);
-		weights->pushSlot(new ValueEditControl<float>(tmp,&poseMC->getOutputCmd(i).weight));
-	}
+	for(unsigned int i=0; i<NumOutputs; i++)
+		weights->pushSlot(new ValueEditControl<float>(outputNames[i],&pose(i).weight));
 
 	pushSlot(NULL); // a separator for clarity
 
 	// add actual value editors
-	for(unsigned int i=0; i<NumOutputs; i++) {
-		std::string tmp(outputNames[i]);
-		pushSlot(new ValueEditControl<float>(tmp,&poseMC->getOutputCmd(i).value));
-	}
+	for(unsigned int i=0; i<NumOutputs; i++)
+		pushSlot(new ValueEditControl<float>(outputNames[i],&pose(i).value));
 }
 
 ControlBase *
 PostureEditor::activate(MotionManager::MC_ID disp_id, Socket * gui) {
+	//cout << "activate" << endl;
 	// start off with current pose
-	poseMC->takeSnapshot();
+	pose.takeSnapshot();
 	// clear the LEDs though
 	for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
-		poseMC->setOutputCmd(i,0);
-	// add it to motion manager above estop
-	poseID=motman->addMotion(poseMC,MotionManager::kEmergencyPriority+1,false);
+		pose.setOutputCmd(i,0);
+	// add it the motion sequence we'll be using to move to changes
+	SharedObject<reach_t> reach;
+	reachID=motman->addPersistentMotion(reach);
+	// we'll need to know when estop is turned on or off
+	erouter->addListener(this,EventBase::estopEGID);
 	// call super class
 	return ControlBase::activate(disp_id,gui);
 }
 
 void
 PostureEditor::refresh() {
+	//cout << "refresh" << endl;
+	if(isEStopped()) {
+		erouter->addTimer(this,0,500);
+		options[0]=NULL;
+	} else {
+		options[0]=loadPose;
+	}
 	if(lastSlot==loadPose) {
 		// we just got back from the load menu
-		MMAccessor<PostureMC>(poseID)->LoadFile(loadPose->getLastInput().c_str());
+		pose.LoadFile(loadPose->getLastInput().c_str());
+		updatePose(moveTime);
 	} else if(lastSlot==savePose || savePose->getLastInput().size()>0) {
 		// we just got back from the save menu
-		MMAccessor<PostureMC>(poseID)->SaveFile(config->motion.makePath(savePose->getLastInput()).c_str());
+		pose.SaveFile(config->motion.makePath(savePose->getLastInput()).c_str());
 		savePose->takeInput("");
+	} else {
+		updatePose(moveTime/2);
 	}
 	lastSlot=NULL;
+	pauseCalled=false;
 	ControlBase::refresh();
 }
 
 void
+PostureEditor::pause() {
+	//cout << "paused" << endl;
+	pauseCalled=true;
+	erouter->removeListener(this,EventBase::timerEGID);
+}
+
+void
 PostureEditor::deactivate() {
-	motman->removeMotion(poseID);
-	poseID=MotionManager::invalid_MC_ID;
+	//cout << "deactivate" << endl;
+	motman->removeMotion(reachID);
+	reachID=MotionManager::invalid_MC_ID;
+	erouter->removeListener(this);
 	ControlBase::deactivate();
 }
 
@@ -71,6 +99,50 @@
 	return ControlBase::doSelect();
 }
 
+void
+PostureEditor::processEvent(const EventBase& e) {
+	if(e.getGeneratorID()==EventBase::estopEGID) {
+		if(e.getTypeID()==EventBase::deactivateETID) {
+			MMAccessor<reach_t>(reachID)->play();
+			erouter->removeListener(this,EventBase::timerEGID);
+			if(!pauseCalled)
+				refresh();
+		} else {
+			if(!pauseCalled) {
+				erouter->addTimer(this,0,500);
+				processEvent(EventBase(EventBase::timerEGID,0,EventBase::statusETID));
+			}
+		}
+	} else if(e.getGeneratorID()==EventBase::timerEGID) {
+		//doing a manual copy instead of just takeSnapshot() so we don't disturb the LED settings
+		for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; i++)
+			pose(i).value=state->outputs[i];
+		refresh();
+	} else {
+		serr->printf("WARNING: PostureEditor unexpected event: %s\n",e.getName().c_str());
+	}
+}
+
+bool
+PostureEditor::isEStopped() {
+	return MMAccessor<EmergencyStopMC>(estopID)->getStopped();
+}
+
+void
+PostureEditor::updatePose(unsigned int delay) {
+	bool paused=isEStopped();
+	MMAccessor<reach_t> reach_acc(reachID);
+	reach_acc->clear();
+	reach_acc->setPlayTime(delay);
+	reach_acc->setPose(pose);
+	reach_acc->setPlayTime(delay+100);
+	reach_acc->setPose(pose);
+	if(paused)
+		reach_acc->pause();
+	else
+		reach_acc->play();
+}
+
 
 /*! @file
  * @brief Describes PostureEditor, which allows numeric control of joints and LEDs
@@ -78,7 +150,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2004/01/30 01:48:02 $
+ * $Date: 2004/10/18 19:53:02 $
  */
Index: Behaviors/Controls/PostureEditor.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/PostureEditor.h,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- Behaviors/Controls/PostureEditor.h	18 Jan 2004 10:16:56 -0000	1.2
+++ Behaviors/Controls/PostureEditor.h	18 Oct 2004 19:53:02 -0000	1.4
@@ -4,36 +4,43 @@
 
 #include "ControlBase.h"
 #include "Shared/SharedObject.h"
-#include "Motion/PostureMC.h"
+#include "Motion/PostureEngine.h"
 #include "Motion/MotionManager.h"
 #include "StringInputControl.h"
 #include "FileInputControl.h"
+#include "Events/EventListener.h"
 
 //! allows logging of events to the console or a file
-class PostureEditor : public ControlBase {
+class PostureEditor : public ControlBase, public EventListener {
 public:
 	//! constructor
-	PostureEditor();
+	explicit PostureEditor(MotionManager::MC_ID estop_ID);
 
-	//! adds #poseMC to MotionManager
 	virtual ControlBase * activate(MotionManager::MC_ID disp_id, Socket * gui);
-
-	//! if we're back from a child slot, it's either load or save, so we need to handle it
-	virtual void refresh();
-
-	//! removes #poseMC from MotionManager
+	virtual void refresh(); //!< if we're back from a child slot, it's either load or save, so we need to handle it
+	virtual void pause();
 	virtual void deactivate();
 
 	//! opens a custom (embedded) menu edit outputs
 	virtual ControlBase* doSelect();
 	
+	//! listens for the EStop to be turned off before moving
+	virtual void processEvent(const EventBase& e);
+	
 protected:
-	SharedObject<PostureMC> poseMC; //!< the actual memory space for the posture
-	MotionManager::MC_ID poseID; //!< current id for the posture
+	PostureEngine pose; //!< the current target posture
+	MotionManager::MC_ID reachID; //!< id of motion sequence used to slow "snapping" to positions
+	MotionManager::MC_ID estopID; //!< so we can check if the estop is active
 
 	ControlBase* lastSlot; //!< the last accessed slot
 	FileInputControl* loadPose; //!< the control for loading postures
 	StringInputControl* savePose; //!< the control for saving postures
+	bool pauseCalled; //!< true if refresh hasn't been called since pause
+	
+	static const unsigned int moveTime=1500; //!< number of milliseconds to take to load a posture - individual joint changes will be done in half the time
+	
+	bool isEStopped(); //!< called to check status of estop
+	void updatePose(unsigned int delay); //!< called anytime pose is modified; uses #reachID to move to #pose if estop is off, setting up #ledID otherwise
 
 private:
 	PostureEditor(const PostureEditor& ); //!< don't call
@@ -46,9 +53,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.4 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/18 19:53:02 $
  */
 
 #endif
Index: Behaviors/Controls/RunSequenceControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/RunSequenceControl.h,v
retrieving revision 1.10
retrieving revision 1.14
diff -u -d -r1.10 -r1.14
--- Behaviors/Controls/RunSequenceControl.h	14 Jul 2003 06:55:14 -0000	1.10
+++ Behaviors/Controls/RunSequenceControl.h	18 Oct 2004 17:01:38 -0000	1.14
@@ -4,21 +4,31 @@
 
 #include "FileBrowserControl.h"
 #include "Motion/MotionSequenceMC.h"
+#include "Motion/EmergencyStopMC.h"
+#include "Motion/LedMC.h"
+#include "SoundPlay/SoundManager.h"
+#include "Motion/MMAccessor.h"
 #include "Shared/TimeET.h"
 #include "Shared/Config.h"
 #include <string>
 
 //! Upon activation, loads a position from a file name read from cin (stored in ms/data/motion...)
-/*! The template parameter is passed to MotionSequenceMC's template parameter in order
- *  to specify the number of keyframes to reserve - larger values use more memory, but will allow
- *  you to load more complicated sequences.
+/*! The template parameter is passed to MotionSequenceMC's template
+ *  parameter in order to specify the number of keyframes to reserve -
+ *  larger values use more memory, but will allow you to load more
+ *  complicated sequences.
+ *
+ *  The motion sequence doesn't actually start playing until the
+ *  emergency stop is deactivated.  This avoids either cutting off the
+ *  beginning of the sequence while still in estop, or having to
+ *  override the estop, which may be unexpected.
  */
 template<unsigned int SequenceSize>
 class RunSequenceControl : public FileBrowserControl, public EventListener {
 public:
 	//! Constructor, sets filter to *.mot
 	RunSequenceControl(const std::string& n, MotionManager::MC_ID estop_id)
-		: FileBrowserControl(n,"Runs a motion sequence from a user-specified file",config->motion.root), estopid(estop_id)
+		: FileBrowserControl(n,"Runs a motion sequence from a user-specified file",config->motion.root), estopid(estop_id), ledid(MotionManager::invalid_MC_ID), waitingFile()
 	{
 		setFilter("*.mot");
 	}
@@ -26,24 +36,40 @@
 	//! this is to help reduce the twitch at the end (estop tries to go back to its position when this is removed)
 	virtual void processEvent(const EventBase& event) {
 		erouter->removeListener(this,event);
-		MMAccessor<EmergencyStopMC> estop(estopid);
-		estop->takeSnapshot();
-		estop->setActive(true);
+		runFile();
+		motman->removeMotion(ledid);
 	}
 
 protected:
-	//!does the actual loading of the MotionSequence
-	virtual ControlBase* selectedFile(const std::string& f) {
+	//! loads the motion sequence and runs it
+	void runFile() {
 		//TimeET timer;
-		SharedObject< MotionSequenceMC<SequenceSize> > s(f.c_str());
+		SharedObject< MotionSequenceMC<SequenceSize> > s(waitingFile.c_str());
 		//cout << "Load Time: " << timer.Age() << endl;
-		MMAccessor<EmergencyStopMC>(estopid)->setActive(false);
-		MotionManager::MC_ID id=motman->addMotion(s,MotionManager::kEmergencyPriority+1,true);
-		erouter->addListener(this,EventBase::motmanEGID,id,EventBase::deactivateETID);
+		motman->addPrunableMotion(s,MotionManager::kEmergencyPriority+1);
+		waitingFile="";
+	}
+
+	//!does the actual loading of the MotionSequence
+	virtual ControlBase* selectedFile(const std::string& f) {
+		waitingFile=f;
+		if(!MMAccessor<EmergencyStopMC>(estopid)->getStopped()) {
+			runFile();
+		} else {
+			//we have to wait for the estop to be turned off
+			sndman->PlayFile("donkey.wav");
+			SharedObject<LedMC> led;
+			led->cycle(BotLLEDMask,1000,3,0,0);
+			led->cycle(BotRLEDMask,1000,3,0,500);
+			ledid=motman->addPersistentMotion(led);
+			erouter->addListener(this,EventBase::estopEGID,estopid,EventBase::deactivateETID);
+		}
 		return this;
 	}
 
 	MotionManager::MC_ID estopid; //!< MC_ID of the emergency stop (so we can reset it to the end frame)
+	MotionManager::MC_ID ledid; //!< MC_ID of the led we use to signal there's a MotionSequence lined up
+	std::string waitingFile; //!< filename of the motion sequence waiting to load
 };
 
 /*! @file
@@ -52,9 +78,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
- * $State: Rel $
- * $Date: 2003/07/14 06:55:14 $
+ * $Revision: 1.14 $
+ * $State: Exp $
+ * $Date: 2004/10/18 17:01:38 $
  */
 
 #endif
Index: Behaviors/Controls/SaveWalkControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/SaveWalkControl.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Behaviors/Controls/SaveWalkControl.h	10 Jan 2004 20:10:27 -0000	1.7
+++ Behaviors/Controls/SaveWalkControl.h	26 Mar 2004 00:28:41 -0000	1.8
@@ -18,12 +18,8 @@
 
 	virtual ControlBase * takeInput(const std::string& msg) {
 		if(msg.size()>0) {
-			std::string filename;
-			if(msg[0]=='/')
-				filename=msg;
-			else
-				filename=config->motion.root+"/"+msg;
-			MotionManager::MC_ID id = thewalk==NULL?walk_id:thewalk->getID();
+			std::string filename=config->motion.makePath(msg);
+			MotionManager::MC_ID id = (thewalk==NULL ? walk_id : thewalk->getID() );
 			WalkMC* walk=thewalk;
 			if(id!=MotionManager::invalid_MC_ID)
 				walk = (WalkMC*)motman->checkoutMotion(id);
@@ -52,8 +48,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2004/01/10 20:10:27 $
+ * $Date: 2004/03/26 00:28:41 $
  */
 #endif
Index: Behaviors/Controls/SensorObserverControl.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/SensorObserverControl.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Behaviors/Controls/SensorObserverControl.cc	23 Dec 2003 06:33:41 -0000	1.1
+++ Behaviors/Controls/SensorObserverControl.cc	7 Oct 2004 19:07:04 -0000	1.2
@@ -70,7 +70,7 @@
 		if(numListeners>0)
 			erouter->addListener(this,EventBase::sensorEGID,0);
 		else
-			erouter->forgetListener(this);
+			erouter->removeListener(this);
 	}
 	if(ans==this)
 		refresh();
@@ -133,7 +133,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * $State: Exp $
- * $Date: 2003/12/23 06:33:41 $
+ * $Date: 2004/10/07 19:07:04 $
  */
Index: Behaviors/Controls/StringInputControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/StringInputControl.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Behaviors/Controls/StringInputControl.h	25 Sep 2003 15:26:11 -0000	1.4
+++ Behaviors/Controls/StringInputControl.h	23 Mar 2004 00:55:01 -0000	1.5
@@ -26,7 +26,10 @@
 	}	
 	
 	//! returns last call to takeInput()
-	virtual std::string getLastInput() { return lastInput; }
+	virtual const std::string& getLastInput() { return lastInput; }
+
+	//! clears the last input (i.e. so you can easily tell later if new input is entered)
+	virtual void clearLastInput() { takeInput(""); }
 
 	//! sets the prompt to give to the user
 	virtual void setPrompt(const std::string& prompt) { userPrompt=prompt; }
@@ -42,9 +45,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
- * $State: Rel $
- * $Date: 2003/09/25 15:26:11 $
+ * $Revision: 1.5 $
+ * $State: Exp $
+ * $Date: 2004/03/23 00:55:01 $
  */
 
 #endif
Index: Behaviors/Controls/ToggleControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/ToggleControl.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Behaviors/Controls/ToggleControl.h	18 Jan 2004 10:16:56 -0000	1.3
+++ Behaviors/Controls/ToggleControl.h	23 Mar 2004 00:55:01 -0000	1.4
@@ -6,7 +6,10 @@
 #include "Shared/ReferenceCounter.h"
 
 //! a simple control for turning things on and off
-/*! Can also be used for radio buttons - select one of a group */
+/*! Can also be used for radio buttons - select one of a group
+ *
+ *  By using the #externalStore (setStore()/getStore()), you can use
+ *  this instead of a ValueEditControl<bool> */
 class ToggleControl : public NullControl {
 public:
 	//! a little class for managing the currently active ToggleControl to allow radio buttons
@@ -43,9 +46,9 @@
 
 	//!@name Constructors
 	//!
-	ToggleControl() : NullControl("[ ] "), rg(NULL) {}
-	ToggleControl(const std::string& n, RadioGroup * rad=NULL) : NullControl("[ ] "+n), rg(NULL) { setRadioGroup(rad); }
-	ToggleControl(const std::string& n, const std::string& d, RadioGroup * rad=NULL) : NullControl("[ ] "+n,d), rg(NULL) { setRadioGroup(rad); }
+	ToggleControl() : NullControl("[ ] "), rg(NULL), externalStore(NULL) {}
+	ToggleControl(const std::string& n, RadioGroup * rad=NULL) : NullControl("[ ] "+n), rg(NULL), externalStore(NULL) { setRadioGroup(rad); }
+	ToggleControl(const std::string& n, const std::string& d, RadioGroup * rad=NULL) : NullControl("[ ] "+n,d), rg(NULL), externalStore(NULL) { setRadioGroup(rad); }
 	//@}
 	~ToggleControl() { setRadioGroup(NULL); } //!< destructor
 
@@ -92,6 +95,8 @@
 			}
 		}
 		name[1]=c;
+		if(externalStore!=NULL)
+			*externalStore=getStatus();
 	}
 
 	//! returns true if there's a non-space as the status
@@ -118,8 +123,13 @@
 	//! returns the current RadioGroup
 	virtual RadioGroup * getRadioGroup() const { return rg; }
 
+	virtual void setStore(bool * s) { externalStore=s; *s=getStatus(); }  //!< sets #externalStore (and updates its current setting)
+	virtual bool * getStore() const { return externalStore; } //!< returns #externalStore
+
 protected:
 	RadioGroup * rg; //!< pointer to an optional radio group to allow one-of-many selections
+	
+	bool * externalStore; //!< an external bit which should be kept in sync with current setting
 
 private:
 	ToggleControl(const ToggleControl& ); //!< don't call
@@ -132,9 +142,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/03/23 00:55:01 $
  */
 
 #endif
Index: Behaviors/Controls/ValueEditControl.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/ValueEditControl.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- Behaviors/Controls/ValueEditControl.h	19 Jan 2004 20:34:51 -0000	1.12
+++ Behaviors/Controls/ValueEditControl.h	7 Oct 2004 19:07:04 -0000	1.13
@@ -35,7 +35,7 @@
 	//!reads in current value from target
 	virtual ControlBase * activate(MotionManager::MC_ID display, Socket * gui) {
 		cur=*target;
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		return StringInputControl::activate(display,gui);
 	}
 	//! will increment/decrement the current and then assign it to the target when head buttons pressed
@@ -167,9 +167,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.13 $
  * $State: Exp $
- * $Date: 2004/01/19 20:34:51 $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
 #endif
Index: Behaviors/Controls/WalkCalibration.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Controls/WalkCalibration.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Behaviors/Controls/WalkCalibration.h	18 Jan 2004 10:16:56 -0000	1.5
+++ Behaviors/Controls/WalkCalibration.h	7 Oct 2004 19:07:04 -0000	1.6
@@ -27,7 +27,7 @@
 	virtual void refresh();
 
 	virtual void deactivate() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		ControlBase::deactivate();
 	}
 
@@ -125,9 +125,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
 #endif
Index: Behaviors/Controls/WaypointWalkControl.cc
===================================================================
RCS file: Behaviors/Controls/WaypointWalkControl.cc
diff -N Behaviors/Controls/WaypointWalkControl.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Controls/WaypointWalkControl.cc	17 Oct 2004 01:16:10 -0000	1.11
@@ -0,0 +1,251 @@
+#include "WaypointWalkControl.h"
+#include "ToggleControl.h"
+#include "NullControl.h"
+#include "FileInputControl.h"
+#include "StringInputControl.h"
+#include "ValueEditControl.h"
+#include "Motion/MotionManager.h"
+#include "Motion/WaypointWalkMC.h"
+#include "Motion/WalkMC.h"
+#include "Motion/MMAccessor.h"
+
+WaypointWalkControl::WaypointWalkControl()
+	: ControlBase("WaypointWalkControl","Allows interactive control and execution of a set of waypoints"),
+		isRunning(false), startstopCtl(NULL), loopCtl(NULL), addEgoWPCtl(NULL),
+		addOffWPCtl(NULL), addAbsWPCtl(NULL), loadCtl(NULL), saveCtl(NULL),
+		localizationCtl(NULL), listOffset(0), walk_id(MotionManager::invalid_MC_ID)
+{
+	pushSlot(startstopCtl=new NullControl("Execute","Begin running waypoint list"));
+	pushSlot(loopCtl=new ToggleControl("Loop Waypoints","When last waypoint is reached, start over"));
+	pushSlot(addEgoWPCtl=new NullControl("Add Egocentric Waypoint","Appends a new egocentric waypoint (heading and location relative) at the end of the list"));
+	pushSlot(addOffWPCtl=new NullControl("Add Offset Waypoint","Appends a new offset waypoint (location relative) at the end of the list"));
+	pushSlot(addAbsWPCtl=new NullControl("Add Absolute Waypoint","Appends a new absolute waypoint at the end of the list"));
+	pushSlot(loadCtl=new FileInputControl("Load Waypoints","Reads a path from a file",config->motion.root));
+	loadCtl->setFilter("*.wyp");
+	pushSlot(saveCtl=new StringInputControl("Save Waypoints","Writes the current path to a file"));
+	pushSlot(localizationCtl=new StringInputControl("Drift Error Correction","Enter 3 numbers 'x y a' reprenting current error"));
+	pushSlot(NULL);
+	listOffset=slotsSize();
+}
+
+ControlBase *
+WaypointWalkControl::activate(MotionManager::MC_ID disp_id, Socket * gui) {
+	if(walk_id==MotionManager::invalid_MC_ID) {
+		SharedObject<WaypointWalkMC> walk;
+		walk_id=motman->addPersistentMotion(walk);
+	}
+	return ControlBase::activate(disp_id,gui);
+}
+
+void
+WaypointWalkControl::refresh() {
+	if(saveCtl->getLastInput().size()>0) {
+		sout->printf("Attempting save to %s...\n",saveCtl->getLastInput().c_str());
+		std::string path=config->motion.makePath(saveCtl->getLastInput());
+		MMAccessor<WaypointWalkMC>(walk_id)->SaveWaypointFile(path.c_str());
+		saveCtl->clearLastInput();
+	}
+	if(loadCtl->getLastInput().size()>0) {
+		sout->printf("Attempting load from %s...\n",loadCtl->getLastInput().c_str());
+		MMAccessor<WaypointWalkMC>(walk_id)->LoadWaypointFile(loadCtl->getLastInput().c_str());
+		loadCtl->clearLastInput();
+	}
+	if(localizationCtl->getLastInput().size()>0) {
+		float x=0,y=0,a=0;
+		sscanf(localizationCtl->getLastInput().c_str(),"%g %g %g",&x,&y,&a);
+		MMAccessor<WaypointWalkMC> walk(walk_id);
+		walk->setCurPos(x+walk->getCurX(),y+walk->getCurY(),a+walk->getCurA());
+		cout << "Position is now " << walk->getCurX() << ' ' << walk->getCurY() << ' ' << walk->getCurA() << endl;
+		localizationCtl->clearLastInput();
+	}
+	
+	MMAccessor<WaypointWalkMC> walk(walk_id);
+
+	loopCtl->setStatus(walk->getIsLooping());
+
+	//rebuild waypoint list
+
+	//clear old entries
+	for(unsigned int i=listOffset; i<slotsSize(); i++)
+		delete options[i];
+	options.resize(listOffset);
+
+	//add new entries
+	WaypointWalkMC::WaypointList_t& wplist=walk->getWaypointList();
+	unsigned int wpcnt=1;
+	for(WaypointWalkMC::WaypointListIter_t it=wplist.begin(); it!=wplist.end(); it=wplist.next(it)) {
+		char cname[50];
+		sprintf(cname,"Waypoint %d",wpcnt++);
+		char desc[100];
+		const char * pt=NULL;
+		switch(wplist[it].posType) {
+		case WaypointWalkMC::Waypoint::POSTYPE_EGOCENTRIC:
+			pt="^="; break; //uhh, the '^' is supposed to imply it's heading-relative :-}
+		case WaypointWalkMC::Waypoint::POSTYPE_OFFSET:
+			pt="+="; break;
+		case WaypointWalkMC::Waypoint::POSTYPE_ABSOLUTE:
+			pt="="; break;
+		}
+		sprintf(desc,"x%s%g, y%s%g, a%s%g, arc=%g", pt,wplist[it].x,pt,wplist[it].y,
+						(wplist[it].angleIsRelative?"+=":"="),wplist[it].angle,wplist[it].arc);
+		pushSlot(new WaypointEditControl(cname,desc,walk_id,it));
+	}
+	ControlBase::refresh();
+}
+
+void
+WaypointWalkControl::deactivate() {
+	motman->removeMotion(walk_id);
+	walk_id=MotionManager::invalid_MC_ID;
+	ControlBase::deactivate();
+}
+
+ControlBase*
+WaypointWalkControl::doSelect() {
+	for(unsigned int i=0; i<hilights.size(); i++) {
+		ControlBase * curctl=options[hilights[i]];
+		if(curctl==startstopCtl) {
+			if(isRunning) {
+				isRunning=false;
+				startstopCtl->setName("Execute");
+				startstopCtl->setDescription("Begin running waypoint list");
+				MMAccessor<WaypointWalkMC>(walk_id)->pause();
+			} else {
+				isRunning=true;
+				startstopCtl->setName("Stop");
+				startstopCtl->setDescription("Halt locomotion");
+				MMAccessor<WaypointWalkMC>(walk_id)->go();
+			}
+			sndman->PlayFile(config->controller.select_snd);
+			return curctl;
+		} else if(curctl==loopCtl) {
+			MMAccessor<WaypointWalkMC>(walk_id)->setIsLooping(!loopCtl->getStatus());
+			sndman->PlayFile(config->controller.select_snd);
+			return curctl;
+		} else if(curctl==addEgoWPCtl) {
+			MMAccessor<WaypointWalkMC>(walk_id)->addEgocentricWaypoint(0,0,false,true,.1);
+			sndman->PlayFile(config->controller.select_snd);
+			return curctl;
+		} else if(curctl==addOffWPCtl) {
+			MMAccessor<WaypointWalkMC>(walk_id)->addOffsetWaypoint(0,0,false,true,.1);
+			sndman->PlayFile(config->controller.select_snd);
+			return curctl;
+		} else if(curctl==addAbsWPCtl) {
+			MMAccessor<WaypointWalkMC>(walk_id)->addAbsoluteWaypoint(0,0,false,true,.1);
+			sndman->PlayFile(config->controller.select_snd);
+			return curctl;
+		}
+	}
+	return ControlBase::doSelect();
+}
+	
+WaypointWalkControl::WaypointEditControl::WaypointEditControl(const std::string& n, const std::string& d, MotionManager::MC_ID walkid, unsigned int waypointid)
+	: ControlBase(n,d), walk_id(walkid), waypoint_id(waypointid), up(NULL), down(NULL), del(NULL), set(NULL)
+{
+	pushSlot(up=new NullControl("Up (Move up)","Moves up in waypoint list"));
+	pushSlot(down=new NullControl("Down (Move down)","Moves down in waypoint list"));
+	pushSlot(del=new NullControl("Delete","Removes from waypoint list"));
+	pushSlot(set=new NullControl("Set as current goal","Starts trying to reach this location"));
+	pushSlot(NULL);
+	MMAccessor<WaypointWalkMC> walk(walk_id);
+	WaypointWalkMC::Waypoint& curway=walk->getWaypointList()[waypoint_id];
+	pushSlot(new ValueEditControl<float>("X",&curway.x));
+	pushSlot(new ValueEditControl<float>("Y",&curway.y));
+	pushSlot(new ValueEditControl<float>("A",&curway.angle));
+	pushSlot(new ValueEditControl<float>("Arc",&curway.arc));
+	pushSlot(new ValueEditControl<float>("Speed (in m/s)",&curway.speed));
+	pushSlot(new ValueEditControl<float>("Turn Speed (in rad/s)",&curway.turnSpeed));
+	char desc[256];
+	snprintf(desc,256,"Types: EGO=%d, OFF=%d, ABS=%d",WaypointWalkMC::Waypoint::POSTYPE_EGOCENTRIC,WaypointWalkMC::Waypoint::POSTYPE_OFFSET,WaypointWalkMC::Waypoint::POSTYPE_ABSOLUTE);
+	pushSlot(new ValueEditControl<int>("Pos. coord. system",desc,(int*)&curway.posType));
+	ToggleControl * tmptgl;
+	pushSlot(tmptgl=new ToggleControl("Angle is relative"));
+	tmptgl->setStatus(curway.angleIsRelative);
+	tmptgl->setStore(&curway.angleIsRelative);
+	pushSlot(tmptgl=new ToggleControl("Track path"));
+	tmptgl->setStatus(curway.trackPath);
+	tmptgl->setStore(&curway.trackPath);
+}
+
+ControlBase* WaypointWalkControl::WaypointEditControl::doSelect() {
+	for(unsigned int i=0; i<hilights.size(); i++) {
+		ControlBase * curctl=options[hilights[i]];
+		if(curctl==up) {
+			WaypointWalkMC::WaypointList_t& list=MMAccessor<WaypointWalkMC>(walk_id)->getWaypointList();
+			list.swap(list.prev(waypoint_id),waypoint_id);
+			sndman->PlayFile(config->controller.select_snd);
+			return NULL;
+		} else if(curctl==down) {
+			WaypointWalkMC::WaypointList_t& list=MMAccessor<WaypointWalkMC>(walk_id)->getWaypointList();
+			list.swap(waypoint_id,list.next(waypoint_id));
+			sndman->PlayFile(config->controller.select_snd);
+			return NULL;
+		} else if(curctl==del) {
+			MMAccessor<WaypointWalkMC>(walk_id)->getWaypointList().erase(waypoint_id);
+			sndman->PlayFile(config->controller.select_snd);
+			return NULL;
+		} else if(curctl==set) {
+			MMAccessor<WaypointWalkMC>(walk_id)->setTargetWaypoint(waypoint_id);
+			sndman->PlayFile(config->controller.select_snd);
+			return NULL;
+		}
+	}
+	return ControlBase::doSelect();
+}
+
+
+		/* //basic
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+		*/
+
+		/*
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,1,-M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(-1,0,0,false,.1);
+			walk->addEgocentricWaypoint(0,0,-M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+		*/
+
+		/*
+			walk->addEgocentricWaypoint(1,0,0,true,.1);
+			walk->addEgocentricWaypoint(0,1,0,true,.1);
+			walk->addEgocentricWaypoint(0,1,-M_PI/2,true,.1);
+			walk->addEgocentricWaypoint(-1,0,M_PI/2,false,.1);
+			walk->addEgocentricWaypoint(0,0,-M_PI/2,true,.1);
+		*/
+
+		/* //circle1
+			walk->addEgocentricArc(0,.5,0,true,.1,M_PI);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.1);
+			walk->addEgocentricArc(.5,0,M_PI/2,true,.1,M_PI);
+			walk->addEgocentricWaypoint(0,0,-M_PI/2,true,.1);
+		*/
+
+    /* //circle2
+			walk->addEgocentricArc(0,.25,0,true,.1,M_PI);
+			walk->addEgocentricWaypoint(0,0,M_PI/2,true,.075);
+			walk->addEgocentricArc(.25,0,M_PI/2,true,.1,M_PI);
+			walk->addEgocentricWaypoint(0,0,-M_PI/2,true,.075);
+		*/
+		
+
+
+/*! @file
+ * @brief Implements WaypointWalkControl, which allows interactive control and execution of a set of waypoints 
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.11 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
Index: Behaviors/Controls/WaypointWalkControl.h
===================================================================
RCS file: Behaviors/Controls/WaypointWalkControl.h
diff -N Behaviors/Controls/WaypointWalkControl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Controls/WaypointWalkControl.h	27 Jul 2004 14:33:28 -0000	1.4
@@ -0,0 +1,84 @@
+//-*-c++-*-
+#ifndef INCLUDED_WaypointWalkControl_h_
+#define INCLUDED_WaypointWalkControl_h_
+
+#include "ControlBase.h"
+#include "Shared/SharedObject.h"
+
+class NullControl;
+class ToggleControl;
+class FileInputControl;
+class StringInputControl;
+
+//! Allows interactive control and execution of a set of waypoints 
+class WaypointWalkControl : public ControlBase {
+public:
+	//!constructor
+	WaypointWalkControl();
+
+	//! add #walk to ::motman
+	virtual ControlBase * activate(MotionManager::MC_ID disp_id, Socket * gui);
+
+	//!will be called after each waypoint is reached so we can update the menu
+	virtual void refresh();
+
+	//! remove the #walk from ::motman
+	virtual void deactivate(); 
+
+	//!handles selection of menu items
+	virtual ControlBase* doSelect();
+	
+	// sends all events received to stdout and/or logfile
+	//virtual void processEvent(const EventBase& event);
+
+	//! handles editing of individual waypoints
+	class WaypointEditControl : public ControlBase {
+	public:
+		//!constructor
+		WaypointEditControl(const std::string& n, const std::string& d, MotionManager::MC_ID walkid, unsigned int waypointid);
+		//!handles selection of menu items
+		virtual ControlBase* doSelect();
+	protected:
+		MotionManager::MC_ID walk_id; //!< id number of the WaypointWalk
+		unsigned int waypoint_id; //!< id of the waypoint this is editing
+		NullControl * up;  //!< command to move up in list
+		NullControl * down;//!< command to move down in list
+		NullControl * del; //!< command to delete from list
+		NullControl * set; //!< command to start targeting this location
+	private:
+		WaypointEditControl(const WaypointEditControl&); //!< don't call
+		WaypointEditControl operator=(const WaypointEditControl&); //!< don't call
+	};
+
+protected:
+	bool isRunning; //!< true if #walk is currently running
+	NullControl * startstopCtl; //!< start and stop waypoint running
+	ToggleControl * loopCtl; //!< repeat waypoints
+	NullControl * addEgoWPCtl; //!< start and stop waypoint running
+	NullControl * addOffWPCtl; //!< start and stop waypoint running
+	NullControl * addAbsWPCtl; //!< start and stop waypoint running
+	FileInputControl * loadCtl; //!< allows loading of a path
+	StringInputControl * saveCtl; //!< save a path to a file
+	StringInputControl * localizationCtl; //!< enter localization updates manually
+
+	unsigned int listOffset; //!< the index of the first waypoint in the menu
+
+	MotionManager::MC_ID walk_id; //!< id number of the walk we're using, so we can check it out before modifying it
+
+private:
+	WaypointWalkControl(const WaypointWalkControl&); //!< don't call
+	WaypointWalkControl operator=(const WaypointWalkControl&); //!< don't call
+};
+
+/*! @file
+ * @brief Describes WaypointWalkControl, which allows interactive control and execution of a set of waypoints 
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.4 $
+ * $State: Exp $
+ * $Date: 2004/07/27 14:33:28 $
+ */
+
+#endif
Index: Behaviors/Demos/ASCIIVisionBehavior.cc
===================================================================
RCS file: Behaviors/Demos/ASCIIVisionBehavior.cc
diff -N Behaviors/Demos/ASCIIVisionBehavior.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/ASCIIVisionBehavior.cc	19 Oct 2004 16:37:00 -0000	1.1
@@ -0,0 +1,35 @@
+#include "ASCIIVisionBehavior.h"
+#include "Events/FilterBankEvent.h"
+#include "Vision/RawCameraGenerator.h"
+#include "Wireless/Socket.h"
+
+const char ASCIIVisionBehavior::charMap[ASCIIVisionBehavior::charMapSize] = {
+	' ','.','\'','`','^','"',',',':',';','~','-','!','i','l','I','>','<','+','?',')',
+	'1',']','|','/','t','f','j','r','n','u','v','c','z','x','Y','U','J','C','L','Q',
+	'0','O','Z','X','m','w','q','p','d','b','k','h','a','o','*','#','M','W','&','8',
+	'%','B','$','@'
+};
+
+
+void
+ASCIIVisionBehavior::processEvent(const EventBase& e) {
+	const FilterBankEvent& fbkevt=dynamic_cast<const FilterBankEvent&>(e);
+
+	unsigned int layer = 1;
+
+	char charimg[(fbkevt.getWidth(layer)+1)*fbkevt.getHeight(layer)+1];
+	char * curchar=charimg;
+	unsigned char * image = fbkevt.getImage(layer, RawCameraGenerator::CHAN_Y);
+	for (unsigned int y = 0; y < fbkevt.getHeight(layer); y++) {
+		unsigned char * row = image + (y * fbkevt.getStride(layer));
+		for (unsigned int x = 0; x < fbkevt.getWidth(layer); x++) {
+			unsigned char * pixel = row + (x * fbkevt.getIncrement(layer));
+			*curchar++=charMap[(pixel[0]*charMapSize)/256];
+		}
+		*curchar++='\n';
+	}
+	*curchar='\0';
+
+	sout->printf("\n\n%s",charimg);
+}
+
Index: Behaviors/Demos/ASCIIVisionBehavior.h
===================================================================
RCS file: Behaviors/Demos/ASCIIVisionBehavior.h
diff -N Behaviors/Demos/ASCIIVisionBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/ASCIIVisionBehavior.h	19 Oct 2004 00:46:54 -0000	1.2
@@ -0,0 +1,52 @@
+//-*-c++-*-
+
+// This is an empty Behavior template file.
+// Replace ASCIIVisionBehavior and streams low-resolution ASCII-art of the camera image to sout as appropriate, and go to town!
+
+#ifndef INCLUDED_ASCIIVisionBehavior_h_
+#define INCLUDED_ASCIIVisionBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Events/EventRouter.h"
+
+//! streams low-resolution ASCII-art of the camera image to sout
+class ASCIIVisionBehavior : public BehaviorBase {
+public:
+	//! constructor
+	ASCIIVisionBehavior() : BehaviorBase() {}
+
+	static const unsigned int charMapSize=64;
+	static const char charMap[charMapSize];
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		erouter->addListener(this,EventBase::visRawCameraEGID);
+	}
+
+	virtual void DoStop() {
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e);
+
+	virtual std::string getName() const { return "ASCIIVisionBehavior"; }
+
+	static std::string getClassDescription() { return "streams low-resolution ASCII-art of the camera image to sout"; }
+	
+protected:
+	
+};
+
+/*! @file
+ * @brief Defines ASCIIVisionBehavior, which streams low-resolution ASCII-art of the camera image to sout
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.2 $
+ * $State: Exp $
+ * $Date: 2004/10/19 00:46:54 $
+ */
+
+#endif
Index: Behaviors/Demos/AlanBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/AlanBehavior.h,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -d -r1.9 -r1.11
--- Behaviors/Demos/AlanBehavior.h	6 Feb 2004 04:06:50 -0000	1.9
+++ Behaviors/Demos/AlanBehavior.h	17 Oct 2004 01:16:10 -0000	1.11
@@ -27,7 +27,7 @@
 		//now do your code:
 		
 		// creates a PostureMC class to move the joint(s) and adds it to global MotionManager
-		pose_id=motman->addMotion(SharedObject<PostureMC>(),false);
+		pose_id=motman->addPersistentMotion(SharedObject<PostureMC>());
 		// subscribe to sensor updated events through the global EventRouter
 		erouter->addListener(this,EventBase::sensorEGID,SensorSourceID::UpdatedSID);
 	}
@@ -35,7 +35,7 @@
 	virtual void DoStop() {
 		//do your code first:
 		motman->removeMotion(pose_id);  // removes your posture controller
-		erouter->forgetListener(this); // stops getting events (and timers, if we had any)
+		erouter->removeListener(this); // stops getting events (and timers, if we had any)
 
 		//but don't forget to call superclass at the end:
 		BehaviorBase::DoStop();
@@ -70,7 +70,7 @@
 				//only really works on the ERS-210 or ERS-7 models - the others don't have a proper pressure sensor
 				//(the 220's antenna-thing is close, but doesn't give a continuous range)
 				std::cout << "Unknown model" << std::endl;
-				erouter->forgetListener(this); // stops getting events (and timers, if we had any)
+				erouter->removeListener(this); // stops getting events (and timers, if we had any)
 				return;
 			}
 			
@@ -117,9 +117,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.11 $
  * $State: Exp $
- * $Date: 2004/02/06 04:06:50 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/AutoGetupBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/AutoGetupBehavior.h,v
retrieving revision 1.9
retrieving revision 1.12
diff -u -d -r1.9 -r1.12
--- Behaviors/Demos/AutoGetupBehavior.h	25 Sep 2003 15:26:22 -0000	1.9
+++ Behaviors/Demos/AutoGetupBehavior.h	17 Oct 2004 01:16:10 -0000	1.12
@@ -26,7 +26,7 @@
 	}
 	//! Stops listening for events
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		BehaviorBase::DoStop();
 	}
 	//! Run appropriate motion script if the robot falls over
@@ -53,7 +53,7 @@
 			else
 				gu=config->motion.makePath("gu_front.mot");
 			SharedObject< MotionSequenceMC<MotionSequence::SizeMedium> > getup(gu.c_str());
-			MotionManager::MC_ID id=motman->addMotion(getup,MotionManager::kHighPriority);
+			MotionManager::MC_ID id=motman->addPrunableMotion(getup,MotionManager::kHighPriority);
 			erouter->addListener(this,EventBase::motmanEGID,id,EventBase::deactivateETID);
 			waiting=true;
 		}
@@ -75,9 +75,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
- * $State: Rel $
- * $Date: 2003/09/25 15:26:22 $
+ * $Revision: 1.12 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/BanditMachine.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/BanditMachine.h,v
retrieving revision 1.13
retrieving revision 1.17
diff -u -d -r1.13 -r1.17
--- Behaviors/Demos/BanditMachine.h	8 Dec 2003 00:20:57 -0000	1.13
+++ Behaviors/Demos/BanditMachine.h	17 Oct 2004 01:16:10 -0000	1.17
@@ -65,7 +65,7 @@
 		lie->setOutputCmd(RFrLegOffset+RotatorOffset,.73);
 		lie->setOutputCmd(LFrLegOffset+KneeOffset,.6);
 		lie->setOutputCmd(RFrLegOffset+KneeOffset,.6);
-		liedown=motman->addMotion(lie);
+		liedown=motman->addPrunableMotion(lie);
 	}
 
 	virtual void DoStop() {
@@ -93,7 +93,7 @@
 			press->setOutputCmd(idx,.3);
 			press->setPlayTime(1500);
 			press->setOutputCmd(idx,outputRanges[idx][MinRange]);
-			press_id=motman->addMotion(press,MotionManager::kStdPriority+1,false);
+			press_id=motman->addPersistentMotion(press,MotionManager::kStdPriority+1);
 		}
 		//!destructor
 		virtual ~PressNode() {
@@ -164,7 +164,7 @@
 		WaitNode(const char* n, StateNode* p, karmedbanditExp3_1& bandito)
 			: StateNode(n,p), b(bandito), reward(false), leds_id(MotionManager::invalid_MC_ID)
 		{
-			leds_id=motman->addMotion(SharedObject<LedMC>());
+			leds_id=motman->addPersistentMotion(SharedObject<LedMC>());
 		}
 		//! destructor
 		virtual ~WaitNode() {
@@ -178,7 +178,7 @@
 			leds->cflash(BotLLEDMask+BotRLEDMask,1,1000);
 		}
 		virtual void DoStop() {
-			erouter->forgetListener(this);
+			erouter->removeListener(this);
 			b.reward(reward);
 			cout << endl;
 			reward=false;
@@ -193,7 +193,7 @@
 				MMAccessor<LedMC> leds(leds_id);
 				leds->cflash(MidLLEDMask+MidRLEDMask,1,100);
 			}
-			erouter->forgetListener(this);
+			erouter->removeListener(this);
 		}
 	protected:
 		karmedbanditExp3_1& b; //!< the class implimenting a k-armed bandit algorithm to pass the reward back to
@@ -217,9 +217,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.13 $
+ * $Revision: 1.17 $
  * $State: Exp $
- * $Date: 2003/12/08 00:20:57 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/BatteryMonitorBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/BatteryMonitorBehavior.h,v
retrieving revision 1.14
retrieving revision 1.19
diff -u -d -r1.14 -r1.19
--- Behaviors/Demos/BatteryMonitorBehavior.h	9 Jan 2004 04:41:05 -0000	1.14
+++ Behaviors/Demos/BatteryMonitorBehavior.h	17 Oct 2004 01:16:10 -0000	1.19
@@ -12,6 +12,7 @@
 #include "Motion/LedMC.h"
 #include "Shared/ERS210Info.h"
 #include "Shared/ERS220Info.h"
+#include "Shared/ERS7Info.h"
 #include "Motion/MMAccessor.h"
 
 //! A background behavior which will monitor the power level and flip the ears when appropriate on a 210, or blink the headlight if a 220
@@ -43,7 +44,7 @@
 	virtual void DoStop() {
 		if(pose!=NULL)
 			stopWarning();
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		BehaviorBase::DoStop();
 	}
 	//! Adds a BatteryMonitorMC to motman if power goes low
@@ -103,11 +104,11 @@
 	//! adds a pose and a timer to get the ears flipping
 	void startWarning() {
 		serr->printf("LOW BATTERY\n");
-		pose_id=motman->addMotion(SharedObject<PostureMC>(),MotionManager::kEmergencyPriority+1,false);
+		pose_id=motman->addPersistentMotion(SharedObject<PostureMC>(),MotionManager::kEmergencyPriority+1);
 		pose=(PostureMC*)motman->peekMotion(pose_id);
 		SharedObject<LedMC> led;
 		led->displayPercent(state->sensors[PowerRemainOffset],LedEngine::major,LedEngine::major);
-		led_id=motman->addMotion(led,MotionManager::kEmergencyPriority+1);
+		led_id=motman->addPersistentMotion(led,MotionManager::kEmergencyPriority+1);
 		setFlipper(true);
 		erouter->addTimer(this,2,128,false);
 	}
@@ -137,6 +138,9 @@
 				pose->setOutputCmd(i,set?!state->outputs[i]:OutputCmd());
 		if(state->robotDesign & WorldState::ERS220Mask)
 			pose->setOutputCmd(ERS220Info::RetractableHeadLEDOffset,set?(state->outputs[ERS220Info::RetractableHeadLEDOffset]>.5?0:1):OutputCmd());
+		if(state->robotDesign & WorldState::ERS7Mask)
+			for(unsigned int i=ERS7Info::EarOffset; i<ERS7Info::EarOffset+ERS7Info::NumEarJoints; i++)
+				pose->setOutputCmd(i,set?!state->outputs[i]:OutputCmd());
 	}
 	PostureMC* pose; //!< if we are currently warning of low battery, holds a pose, NULL otherwise
 	MotionManager::MC_ID pose_id; //!< id of pose if we are currently warning, MotionManager::invalid_MC_ID otherwise
@@ -153,9 +157,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.14 $
+ * $Revision: 1.19 $
  * $State: Exp $
- * $Date: 2004/01/09 04:41:05 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/CameraBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/CameraBehavior.cc,v
retrieving revision 1.4
retrieving revision 1.7
diff -u -d -r1.4 -r1.7
--- Behaviors/Demos/CameraBehavior.cc	5 Feb 2004 23:33:27 -0000	1.4
+++ Behaviors/Demos/CameraBehavior.cc	17 Oct 2004 01:16:10 -0000	1.7
@@ -33,12 +33,12 @@
 	}
 	initIndex();
 	sndman->LoadFile("camera.wav");
-	ledID=motman->addMotion(SharedObject<LedMC>());
+	ledID=motman->addPersistentMotion(SharedObject<LedMC>());
 	erouter->addListener(this,camera_click);
 }
 
 void CameraBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	sndman->ReleaseFile("camera.wav");
 	motman->removeMotion(ledID);
 	BehaviorBase::DoStop();
@@ -197,8 +197,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2004/02/05 23:33:27 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Demos/ChaseBallBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/ChaseBallBehavior.cc,v
retrieving revision 1.8
retrieving revision 1.11
diff -u -d -r1.8 -r1.11
--- Behaviors/Demos/ChaseBallBehavior.cc	9 Dec 2003 17:33:14 -0000	1.8
+++ Behaviors/Demos/ChaseBallBehavior.cc	17 Oct 2004 01:16:10 -0000	1.11
@@ -12,13 +12,13 @@
 
 void ChaseBallBehavior::DoStart() {
 	BehaviorBase::DoStart();
-	headpointer_id = motman->addMotion(SharedObject<HeadPointerMC>());
-	walker_id = motman->addMotion(SharedObject<WalkMC>());
+	headpointer_id = motman->addPersistentMotion(SharedObject<HeadPointerMC>());
+	walker_id = motman->addPersistentMotion(SharedObject<WalkMC>());
 	erouter->addListener(this,EventBase::visObjEGID,ProjectInterface::visPinkBallSID);
 }
 
 void ChaseBallBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	motman->removeMotion(headpointer_id);
 	motman->removeMotion(walker_id);
 	BehaviorBase::DoStop();
@@ -65,9 +65,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.11 $
  * $State: Exp $
- * $Date: 2003/12/09 17:33:14 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 
Index: Behaviors/Demos/CrashTestBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/CrashTestBehavior.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Behaviors/Demos/CrashTestBehavior.h	3 Oct 2003 03:40:17 -0000	1.1
+++ Behaviors/Demos/CrashTestBehavior.h	25 Aug 2004 01:07:45 -0000	1.2
@@ -30,7 +30,7 @@
 	
 	static std::string getClassDescription() {
 		// This string will be shown by the HelpControl or by the tooltips of the Controller GUI
-		return "A little demo of blocking output before a crash (yes, this crashes the AIBO)";
+		return "A little demo of blocking output before a crash after output #33 (yes, this crashes the AIBO)";
 	}
 	
 };
@@ -41,9 +41,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.1 $
- * $State: Rel $
- * $Date: 2003/10/03 03:40:17 $
+ * $Revision: 1.2 $
+ * $State: Exp $
+ * $Date: 2004/08/25 01:07:45 $
  */
 
 #endif
Index: Behaviors/Demos/DriveMeBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/DriveMeBehavior.cc,v
retrieving revision 1.4
retrieving revision 1.7
diff -u -d -r1.4 -r1.7
--- Behaviors/Demos/DriveMeBehavior.cc	25 Jul 2003 20:18:04 -0000	1.4
+++ Behaviors/Demos/DriveMeBehavior.cc	17 Oct 2004 01:16:10 -0000	1.7
@@ -33,9 +33,9 @@
 {
   BehaviorBase::DoStart();
   // Insert walker into motion manager
-  walker_id = motman->addMotion(SharedObject<WalkMC>());
+  walker_id = motman->addPersistentMotion(SharedObject<WalkMC>());
   // Insert standing pose into motion manager
-  stand_id = motman->addMotion(stand, MotionManager::kStdPriority+1, false);
+  stand_id = motman->addPersistentMotion(stand, MotionManager::kStdPriority+1);
   // We listen to timers
   erouter->addListener(this, EventBase::timerEGID);
   // Turn on timer that goes off now to take us immediately to processEvent
@@ -48,7 +48,7 @@
   // We're not listening to timers anymore.
   erouter->removeTimer(this);
   // We're not listening to *anything* anymore! (also kills timers on its own)
-  erouter->forgetListener(this);
+  erouter->removeListener(this);
   // remove walker and stander from motion manager
   motman->removeMotion(walker_id);
   motman->removeMotion(stand_id);
@@ -110,8 +110,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
- * $State: Rel $
- * $Date: 2003/07/25 20:18:04 $
+ * $Revision: 1.7 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Demos/ExploreMachine.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/ExploreMachine.h,v
retrieving revision 1.16
retrieving revision 1.19
diff -u -d -r1.16 -r1.19
--- Behaviors/Demos/ExploreMachine.h	19 Jan 2004 20:34:56 -0000	1.16
+++ Behaviors/Demos/ExploreMachine.h	17 Oct 2004 01:16:10 -0000	1.19
@@ -43,7 +43,7 @@
 		}
 
 		SharedObject<WalkMC> walk;
-		walkid=motman->addMotion(walk);
+		walkid=motman->addPersistentMotion(walk);
 		WalkNode * move=NULL;
 		start=addNode(turn=new WalkNode(0,0,0.5f,this));
 		turn->setName(getName()+"::turn");
@@ -66,7 +66,7 @@
 	}
 
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		StateNode::DoStop();
 	}
 
@@ -103,9 +103,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.16 $
+ * $Revision: 1.19 $
  * $State: Exp $
- * $Date: 2004/01/19 20:34:56 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/FollowHeadBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/FollowHeadBehavior.cc,v
retrieving revision 1.5
retrieving revision 1.8
diff -u -d -r1.5 -r1.8
--- Behaviors/Demos/FollowHeadBehavior.cc	6 Jan 2004 01:00:44 -0000	1.5
+++ Behaviors/Demos/FollowHeadBehavior.cc	17 Oct 2004 01:16:10 -0000	1.8
@@ -23,7 +23,7 @@
 void FollowHeadBehavior::DoStart() {
 	BehaviorBase::DoStart();
 	//set up the shared motions
-	walker_id=motman->addMotion(SharedObject<WalkMC>());
+	walker_id=motman->addPersistentMotion(SharedObject<WalkMC>());
 	//register for events and timers
 	erouter->addListener(this,head_release);
 	erouter->addListener(this,head_lock);
@@ -34,7 +34,7 @@
 
 void FollowHeadBehavior::DoStop() {
 	//remove timers and listeners
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	//remove motion commands, set them to invalid
 	motman->removeMotion(walker_id);
 	walker_id=MotionManager::invalid_MC_ID;
@@ -52,12 +52,12 @@
 
 	} else if(e==head_release) {
 		cout << "release" << endl;
-		motman->addMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0));
+		motman->addPrunableMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0));
 		erouter->addListener(this,clock);
 
 	} else if(e==head_lock) {
 		cout << "lock" << endl;
-		motman->addMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,1));
+		motman->addPrunableMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,1));
 		for(unsigned int i=HeadOffset; i<HeadOffset+NumHeadJoints; i++)
 			motman->setOutput(NULL,i,state->outputs[i]); //doing this prevents the head from jerking back when you released it to where it was before you pressed the button
 		cout << state->outputs[HeadOffset+TiltOffset]/M_PI*180 << ' ' << state->outputs[HeadOffset+PanOffset]/M_PI*180 << ' ' << state->outputs[HeadOffset+RollOffset]/M_PI*180 << endl;
@@ -74,8 +74,8 @@
  *
  * $Author: ejt $
  * $Name $
- * $Revision: 1.5 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2004/01/06 01:00:44 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Demos/FreezeTestBehavior.h
===================================================================
RCS file: Behaviors/Demos/FreezeTestBehavior.h
diff -N Behaviors/Demos/FreezeTestBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/FreezeTestBehavior.h	27 Aug 2004 22:10:10 -0000	1.1
@@ -0,0 +1,56 @@
+//-*-c++-*-
+#ifndef INCLUDED_FreezeTestBehavior_h_
+#define INCLUDED_FreezeTestBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Wireless/Wireless.h"
+
+//! Demonstrates an infinite loop condition in the Main process
+class FreezeTestBehavior : public BehaviorBase {
+public:
+	FreezeTestBehavior() : BehaviorBase()	{}
+	
+	virtual void DoStart() {
+		//call superclass first for housekeeping:
+		BehaviorBase::DoStart();
+
+		//now do your code:
+		const unsigned int start=2500001;
+		serr->printf("Now computing all primes greater than %d... (this might take... forever)\n",start-1);
+		serr->printf("Motion process should be able to continue, but Main process will freeze.\n");
+		for(unsigned int i=start;;i+=2) {
+			unsigned int j=3;
+			const unsigned int irt=(unsigned int)sqrt((double)i);
+			for(; j<=irt; j++)
+				if((i/j)*j==i)
+					break;
+			if(j==irt)
+				serr->printf("%d is prime\n",i);
+		}
+		//Hate to break it to you, but we're never going to get here...
+	}
+	
+	virtual std::string getName() const {
+		// Name is used for menus, or debugging.
+		return "FreezeTestBehavior";
+	}
+	
+	static std::string getClassDescription() {
+		// This string will be shown by the HelpControl or by the tooltips of the Controller GUI
+		return "A little demo of a Main process infinite loop freeze (yes, this hangs the AIBO)";
+	}
+	
+};
+
+/*! @file
+ * @brief Defines FreezeTestBehavior, demonstrates (lack of) blocking using serr to (not) pinpoint a crash
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/27 22:10:10 $
+ */
+
+#endif
Index: Behaviors/Demos/GroundPlaneBehavior.h
===================================================================
RCS file: Behaviors/Demos/GroundPlaneBehavior.h
diff -N Behaviors/Demos/GroundPlaneBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/GroundPlaneBehavior.h	17 Oct 2004 01:16:10 -0000	1.6
@@ -0,0 +1,93 @@
+//-*-c++-*-
+
+#ifndef INCLUDED_GroundPlaneBehavior_h_
+#define INCLUDED_GroundPlaneBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/Kinematics.h"
+#include "Motion/PIDMC.h"
+#include "Motion/MotionManager.h"
+#include "Shared/ERS7Info.h"
+#include "Shared/ERS2xxInfo.h"
+#include "Shared/WorldState.h"
+
+//! Reports the location of the center of the camera image on the ground plane
+class GroundPlaneBehavior : public BehaviorBase {
+public:
+	//! constructor
+	GroundPlaneBehavior()
+		: BehaviorBase(),
+			head_release(EventBase::buttonEGID,(state->robotDesign&WorldState::ERS7Mask)?(int)ERS7Info::HeadButOffset:(int)ERS2xxInfo::HeadFrButOffset,EventBase::activateETID,0),
+			head_lock(EventBase::buttonEGID,(state->robotDesign&WorldState::ERS7Mask)?(int)ERS7Info::HeadButOffset:(int)ERS2xxInfo::HeadFrButOffset,EventBase::deactivateETID,0),
+			clock(EventBase::timerEGID,0,EventBase::statusETID,250)
+	{ }
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		erouter->addListener(this,head_release);
+		erouter->addListener(this,head_lock);
+		processEvent(clock);
+	}
+
+	virtual void DoStop() {
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e==clock) {
+			//This is the direction gravity is pulling - probably a good way to find out
+			//the attitude of the robot, assuming it is not moving.
+			//** Note that the LAccel sensor needs to be negated to match the coordinate system **//
+			NEWMAT::ColumnVector down=Kinematics::pack(state->sensors[BAccelOffset],
+			                                           -state->sensors[LAccelOffset],
+			                                           state->sensors[DAccelOffset]);
+			
+			//Just for kicks, lets report which leg is off the ground
+			cout << "I think leg " << kine->findUnusedLeg(down) << " is least used" << endl;
+
+			//First we determine the ground plane
+			NEWMAT::ColumnVector p=kine->calculateGroundPlane(down);
+			cout << "Ground plane: " << p(1)<<"x + " << p(2)<<"y + " << p(3)<<"z = 1" << endl;
+
+			//Project to ground plane - we do it twice here, once for camera frame and once for base frame
+			NEWMAT::ColumnVector ray(4); ray(1)=ray(2)=0; ray(3)=ray(4)=1;
+			NEWMAT::ColumnVector hit;
+			//cout <<"Current head:\n"<<state->outputs[HeadOffset] <<' '<< state->outputs[HeadOffset+1] <<' '<< state->outputs[HeadOffset+2] << endl <<kine->getTransform(CameraFrameOffset);
+			hit=kine->projectToPlane(CameraFrameOffset,ray,BaseFrameOffset,p,CameraFrameOffset);
+			cout << "Intersection_camera: (" << hit(1)<<','<<hit(2)<<','<<hit(3)<<')'<<endl;
+			hit=kine->projectToPlane(CameraFrameOffset,ray,BaseFrameOffset,p,BaseFrameOffset);
+			cout << "Intersection_base: (" << hit(1)<<','<<hit(2)<<','<<hit(3)<<')'<<endl;
+
+		} else if(e==head_release) {
+			motman->addPrunableMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0));
+			erouter->addListener(this,clock);
+			processEvent(clock);
+		} else if(e==head_lock) {
+			motman->addPrunableMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,1));
+			erouter->removeListener(this,clock);
+		} else {
+			ASSERT(false,"unprocessed event " << e.getName() << endl);
+		}
+	}
+
+	virtual std::string getName() const { return "GroundPlaneBehavior"; }
+
+	static std::string getClassDescription() { return "Reports the location of the center of the camera image on the ground plane"; }
+	
+protected:
+	EventBase head_release, head_lock, clock;
+};
+
+/*! @file
+ * @brief Defines GroundPlaneBehavior, which reports the location of the center of the camera image on the ground plane
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.6 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Demos/HeadLevelBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/HeadLevelBehavior.h,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- Behaviors/Demos/HeadLevelBehavior.h	19 Jan 2004 07:55:27 -0000	1.6
+++ Behaviors/Demos/HeadLevelBehavior.h	17 Oct 2004 01:16:10 -0000	1.9
@@ -5,14 +5,14 @@
 #include "Behaviors/BehaviorBase.h"
 #include "Motion/MotionManager.h"
 #include "Motion/MMAccessor.h"
-#include "Motion/HeadPointerMC.h"
+#include "Motion/OldHeadPointerMC.h"
 #include "Motion/PIDMC.h"
 #include <math.h>
 #include "Shared/ERS210Info.h"
 #include "Shared/ERS220Info.h"
 #include "Shared/ERS7Info.h"
 
-//! Tests the head leveling code of HeadPointerMC
+//! Tests the head leveling code of OldHeadPointerMC
 class HeadLevelBehavior : public BehaviorBase {
  public:
 	//! constructor
@@ -43,29 +43,29 @@
 	virtual void DoStart() {
 		BehaviorBase::DoStart();
 		head->setJoints(state->outputs[HeadOffset+TiltOffset],state->outputs[HeadOffset+PanOffset],state->outputs[HeadOffset+RollOffset]);
-		head->setMode(HeadPointerMC::GravityRelative,true);
+		head->setMode(OldHeadPointerMC::GravityRelative,true);
 		head->noMaxSpeed(); // this is probably pretty safe - the whole point is to keep the head still
-		head_id=motman->addMotion(head);
+		head_id=motman->addPersistentMotion(head);
 		erouter->addListener(this,head_lock);
 		erouter->addListener(this,head_release);
 	}
 
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		motman->removeMotion(head_id);
-		head->setMode(HeadPointerMC::BodyRelative,false);
+		head->setMode(OldHeadPointerMC::BodyRelative,false);
 		BehaviorBase::DoStop();
 	}
 
 	virtual void processEvent(const EventBase &event) {
 		if(event==head_lock) {
 			for(unsigned int i=HeadOffset; i<HeadOffset+NumHeadJoints; i++)
-				head->setJointValueFromMode((TPROffset_t)(i-HeadOffset),state->outputs[i],HeadPointerMC::BodyRelative);
+				head->setJointValueFromMode((TPROffset_t)(i-HeadOffset),state->outputs[i],OldHeadPointerMC::BodyRelative);
 			motman->removeMotion(pid_id);
 			pid_id=MotionManager::invalid_MC_ID;
 		} else if(event==head_release) {
-			pid_id=motman->addMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0),MotionManager::kHighPriority,false);
-			//motman->addMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0));
+			pid_id=motman->addPersistentMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0),MotionManager::kHighPriority);
+			//motman->addPersistentMotion(SharedObject<PIDMC>(HeadOffset,HeadOffset+NumHeadJoints,0));
 		} else
 			ASSERTRET(false,"received unasked for event "<<event.getName());
 	}
@@ -75,7 +75,7 @@
  protected:
 	EventBase head_release; //!< event mask for releasing head (chin button down)
 	EventBase head_lock;    //!< event mask for locking head (chin button up)
-	const SharedObject<HeadPointerMC> head; //!< might as well just hang on to the whole memory region and reuse it, we can peek for most of our stuff
+	const SharedObject<OldHeadPointerMC> head; //!< might as well just hang on to the whole memory region and reuse it, we can peek for most of our stuff
 	MotionManager::MC_ID head_id; //!< MCID of headpointer
 	MotionManager::MC_ID pid_id; //!< MCID of pid controller
 };
@@ -86,9 +86,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2004/01/19 07:55:27 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif 
Index: Behaviors/Demos/KinematicSampleBehavior.h
===================================================================
RCS file: Behaviors/Demos/KinematicSampleBehavior.h
diff -N Behaviors/Demos/KinematicSampleBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/KinematicSampleBehavior.h	17 Oct 2004 01:16:10 -0000	1.6
@@ -0,0 +1,122 @@
+//-*-c++-*-
+#ifndef INCLUDED_KinematicSampleBehavior_h_
+#define INCLUDED_KinematicSampleBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/PIDMC.h"
+#include "Motion/PostureMC.h"
+#include "Motion/MotionManager.h"
+#include "Shared/SharedObject.h"
+#include "Motion/roboop/robot.h"
+#include "Shared/Config.h"
+#include "Motion/Kinematics.h"
+
+
+//! Uses kinematics to mirror leg positions (note that it mirrors the paw position - not necessarily the joint angles used to get there!)
+class KinematicSampleBehavior : public BehaviorBase {
+public:
+	//! constructor
+	KinematicSampleBehavior()
+		: BehaviorBase(), lastLeg(LFrLegOrder), poseID(MotionManager::invalid_MC_ID)
+	{ }
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		poseID=motman->addPersistentMotion(SharedObject<PostureMC>());
+		erouter->addListener(this,EventBase::sensorEGID);
+		erouter->addListener(this,EventBase::buttonEGID);
+	}
+
+	virtual void DoStop() {
+		motman->removeMotion(poseID);
+		poseID=MotionManager::invalid_MC_ID;
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e.getGeneratorID()==EventBase::buttonEGID) {
+			switch(e.getSourceID()) {
+			case LFrPawOffset:
+				lastLeg=LFrLegOrder; break;
+			case RFrPawOffset:
+				lastLeg=RFrLegOrder; break;
+			case LBkPawOffset:
+				lastLeg=LBkLegOrder; break;
+			case RBkPawOffset:
+				lastLeg=RBkLegOrder; break;
+			default:
+				return;
+			}
+			if(e.getTypeID()==EventBase::activateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> relaxLeg(lastlegoff,lastlegoff+JointsPerLeg,0);
+				motman->addPrunableMotion(relaxLeg);
+				MMAccessor<PostureMC> pose_acc(poseID);
+				for(unsigned int i=0; i<JointsPerLeg; i++)
+					pose_acc->setOutputCmd(lastlegoff+i,OutputCmd::unused);
+			} else if(e.getTypeID()==EventBase::deactivateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> tightLeg(lastlegoff,lastlegoff+JointsPerLeg,1);
+				motman->addPrunableMotion(tightLeg);
+			}
+
+		} else if(e.getGeneratorID()==EventBase::sensorEGID) {
+			//I'll use the pack and unpack functions here just to illustrate how to avoid 
+			//needing to use NEWMAT data structures - but if you're going to be doing
+			//any significant math, you'll eventually want to get comfortable with NEWMAT...
+
+			// (Actually, I think the NEWMAT version would be more readable...)
+
+			/******** Determine location of target position ********/
+			float link_x=60,link_y=0,link_z=0; // 6cm along x axis of selected joint
+			float obj_x=0, obj_y=0, obj_z=0;   // these will hold the objective position
+			//this next line computes the link position, and stores result into obj_*
+			Kinematics::unpack(kine->linkToBase(getIndex(lastLeg))*Kinematics::pack(link_x,link_y,link_z),
+			                   obj_x,obj_y,obj_z);
+
+			/******** Solve each leg for the point ********/
+			MMAccessor<PostureMC> pose_acc(poseID); //
+			for(unsigned int i=0; i<NumLegs; i++)
+				if(i!=(unsigned int)lastLeg) {
+					float m_x=((i<2)==((unsigned int)lastLeg<2))?obj_x:-obj_x;
+					float m_y=((i%2)==((unsigned int)lastLeg%2))?obj_y:-obj_y;
+					pose_acc->solveLinkPosition(Kinematics::pack(m_x,m_y,obj_z),
+					                            getIndex((LegOrder_t)i),
+					                            Kinematics::pack(link_x,link_y,link_z));
+				}
+			
+			//If you would like to verify the positiions of the back toes... (relative to body center)
+			//cout << "L: " << kine->getFrameInterestPoint(BaseFrameOffset,"ToeLBkPaw").t();
+			//cout << "R: " << kine->getFrameInterestPoint(BaseFrameOffset,"ToeRBkPaw").t();
+			
+		} else {
+			serr->printf("KinematicSampleBehavior: Unhandled event %s\n",e.getName().c_str());
+		}
+	}
+
+	virtual std::string getName() const { return "KinematicSampleBehavior"; }
+
+	static std::string getClassDescription() { return "Uses kinematics to mirror leg positions (note that it mirrors the paw position - not necessarily the joint angles used to get there!)"; }
+	
+protected:
+	unsigned int getIndex(LegOrder_t leg) {
+		//or try: return PawFrameOffset+leg;
+		return LegOffset+leg*JointsPerLeg+KneeOffset;
+	}
+	LegOrder_t lastLeg;
+	MotionManager::MC_ID poseID;
+};
+
+/*! @file
+ * @brief Defines KinematicSampleBehavior, which uses kinematics to mirror leg positions (note that it mirrors the paw position - not necessarily the joint angles used to get there!)
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.6 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Demos/KinematicSampleBehavior2.h
===================================================================
RCS file: Behaviors/Demos/KinematicSampleBehavior2.h
diff -N Behaviors/Demos/KinematicSampleBehavior2.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/KinematicSampleBehavior2.h	19 Oct 2004 17:06:51 -0000	1.9
@@ -0,0 +1,173 @@
+//-*-c++-*-
+#ifndef INCLUDED_KinematicSampleBehavior2_h_
+#define INCLUDED_KinematicSampleBehavior2_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/PIDMC.h"
+#include "Motion/PostureMC.h"
+#include "Motion/MotionManager.h"
+#include "Shared/SharedObject.h"
+#include "Motion/roboop/robot.h"
+#include "Shared/Config.h"
+#include "Motion/Kinematics.h"
+
+
+//! Uses kinematics to make the back toe (Toe{LR}BkPaw) touch the lower thigh (Lower{LeftBackL,RightBackR}FrThigh)
+class KinematicSampleBehavior2 : public BehaviorBase {
+public:
+	//! constructor
+	KinematicSampleBehavior2()
+		: BehaviorBase(), lastLeg(LFrLegOrder), poseID(MotionManager::invalid_MC_ID)
+	{ }
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		poseID=motman->addPersistentMotion(SharedObject<PostureMC>());
+		erouter->addListener(this,EventBase::sensorEGID);
+		erouter->addListener(this,EventBase::buttonEGID);
+	}
+
+	virtual void DoStop() {
+		motman->removeMotion(poseID);
+		poseID=MotionManager::invalid_MC_ID;
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e.getGeneratorID()==EventBase::buttonEGID) {
+			switch(e.getSourceID()) {
+			case LFrPawOffset:
+				lastLeg=LFrLegOrder; break;
+			case RFrPawOffset:
+				lastLeg=RFrLegOrder; break;
+			case LBkPawOffset:
+				lastLeg=LBkLegOrder; break;
+			case RBkPawOffset:
+				lastLeg=RBkLegOrder; break;
+			default:
+				return;
+			}
+			if(e.getTypeID()==EventBase::activateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> relaxLeg(lastlegoff,lastlegoff+JointsPerLeg,0);
+				motman->addPrunableMotion(relaxLeg);
+				MMAccessor<PostureMC> pose_acc(poseID);
+				for(unsigned int i=0; i<JointsPerLeg; i++)
+					pose_acc->setOutputCmd(lastlegoff+i,OutputCmd::unused);
+			} else if(e.getTypeID()==EventBase::deactivateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> tightLeg(lastlegoff,lastlegoff+JointsPerLeg,1);
+				motman->addPrunableMotion(tightLeg);
+			}
+
+		} else if(e.getGeneratorID()==EventBase::sensorEGID) {
+			//Plan A:
+			NEWMAT::ColumnVector obj(4);
+			switch(lastLeg) {
+			case LFrLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerInnerBackLFrThigh,LowerOuterBackLFrThigh"); break;
+			case RFrLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerInnerBackRFrThigh,LowerOuterBackRFrThigh"); break;
+			case LBkLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerInnerFrontLBkThigh"); break;
+			case RBkLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerInnerFrontRBkThigh"); break;
+			}
+			if(obj(4)!=1)
+				return;
+			
+			unsigned int solveLink=PawFrameOffset+((lastLeg+2)%NumLegs); //swap front/back
+			NEWMAT::ColumnVector link(4);
+			switch(lastLeg) {
+			case LFrLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"ToeLBkPaw"); break;
+			case RFrLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"ToeRBkPaw"); break;
+			case LBkLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"LowerInnerBackLFrShin"); break;
+			case RBkLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"LowerInnerBackRFrShin"); break;
+			}
+			if(link(4)!=1)
+				return;
+			
+			//use the knee angle to assign distance from the solution point
+			float dist=state->outputs[LegOffset+lastLeg*JointsPerLeg+KneeOffset];
+			dist*=30/outputRanges[LegOffset+lastLeg*JointsPerLeg+KneeOffset][MaxRange]; //scale to go up to 3 cm away
+			cout << "Distance is " << dist/10 << "cm" << endl;
+			float curlen=sqrt(link.SubMatrix(1,3,1,1).SumSquare());
+			//Two ways to do the same thing:
+			if(lastLeg==LFrLegOrder || lastLeg==LBkLegOrder)
+				link.SubMatrix(1,3,1,1)*=(dist+curlen)/curlen; //scale the vector components individually
+			else
+				link(4)=curlen/(dist+curlen); //scale along the vector using the homogenous coordinate
+
+			//Plan B:
+			/*
+			NEWMAT::ColumnVector obj(4);
+			switch(lastLeg) {
+			case LFrLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerLeftBackLFrShin,LowerRightBackLFrShin"); break;
+			case RFrLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"LowerLeftBackRFrShin,LowerRightBackRFrShin"); break;
+			case LBkLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"ToeLBkPaw"); break;
+			case RBkLegOrder:
+				obj=kine->getFrameInterestPoint(BaseFrameOffset,"ToeRBkPaw"); break;
+			}
+			if(obj(4)!=1)
+				return;
+			
+			unsigned int solveLink=PawFrameOffset+((lastLeg+2)%NumLegs); //swap front/back
+			NEWMAT::ColumnVector link(4);
+			switch(lastLeg) {
+			case LFrLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"ToeLBkPaw"); break;
+			case RFrLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"ToeRBkPaw"); break;
+			case LBkLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"LowerLeftBackLFrShin,LowerRightBackLFrShin"); break;
+			case RBkLegOrder:
+				link=kine->getLinkInterestPoint(solveLink,"LowerLeftBackRFrShin,LowerRightBackRFrShin"); break;
+			}
+			if(link(4)!=1)
+				return;
+			*/
+
+			MMAccessor<PostureMC> pose_acc(poseID);
+			pose_acc->solveLinkPosition(obj,solveLink,link);
+
+			//If you would like to verify the positiions of the back toes... (relative to body center)
+			//cout << "L: " << kine->getFrameInterestPoint(BaseFrameOffset,"ToeLBkPaw").t();
+			//cout << "R: " << kine->getFrameInterestPoint(BaseFrameOffset,"ToeRBkPaw").t();
+			//cout << "Toe: " << pose_acc->getFrameInterestPoint(BaseFrameOffset,"ToeLBkPaw").t();
+			//cout << "PawA: " << pose_acc->getFrameInterestPoint(BaseFrameOffset,"LBkPaw").t();
+			//cout << "PawB: " << (pose_acc->frameToFrame(PawFrameOffset+LBkLegOrder,BaseFrameOffset)*Kinematics::pack(0,0,0)).t();
+			
+		} else {
+			serr->printf("KinematicSampleBehavior2: Unhandled event %s\n",e.getName().c_str());
+		}
+	}
+
+	virtual std::string getName() const { return "KinematicSampleBehavior2"; }
+
+	static std::string getClassDescription() { return "Uses kinematics to make the back toe (Toe{LR}BkPaw) touch the lower thigh (Lower{LeftBackL,RightBackR}FrThigh)"; }
+	
+protected:
+	LegOrder_t lastLeg;
+	MotionManager::MC_ID poseID;
+};
+
+/*! @file
+ * @brief Defines KinematicSampleBehavior2, which uses kinematics to make the back toe (Toe{LR}BkPaw) touch the lower thigh (Lower{LeftBackL,RightBackR}FrThigh)
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.9 $
+ * $State: Exp $
+ * $Date: 2004/10/19 17:06:51 $
+ */
+
+#endif
Index: Behaviors/Demos/LookForSoundBehavior.h
===================================================================
RCS file: Behaviors/Demos/LookForSoundBehavior.h
diff -N Behaviors/Demos/LookForSoundBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/LookForSoundBehavior.h	17 Oct 2004 01:16:10 -0000	1.4
@@ -0,0 +1,73 @@
+//-*-c++-*-
+#ifndef INCLUDED_LookForSoundBehavior_h_
+#define INCLUDED_LookForSoundBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/HeadPointerMC.h"
+#include "Events/DataEvent.h"
+
+//! Turns head to sound source, estimated by average volume difference between left and right ears
+class LookForSoundBehavior : public BehaviorBase {
+public:
+	//! constructor
+	LookForSoundBehavior() : BehaviorBase(), mc_id(MotionManager::invalid_MC_ID){}
+
+	virtual void DoStart()
+	{
+		BehaviorBase::DoStart();
+
+		// You'll listen for sound and move your head
+		mc_id = motman->addPersistentMotion(SharedObject<HeadPointerMC>());
+		erouter->addListener(this,EventBase::micOSndEGID);
+	}
+
+	virtual void DoStop()
+	{
+		motman->removeMotion(mc_id);
+		erouter->removeListener(this);
+		BehaviorBase::DoStop();
+	}
+
+	virtual void processEvent(const EventBase& event)
+	{
+		if( event.getGeneratorID() == EventBase::micOSndEGID) {
+			// Get to the sound buffer, inevitable warning on line 37
+			// getData() is not specified for const data
+			const DataEvent<const OSoundVectorData*> *de = 
+				reinterpret_cast<const DataEvent<const OSoundVectorData*>*>( &event);
+
+			OSoundVectorData *svd = const_cast<OSoundVectorData*>(de->getData());
+			const short *d = ( const short *)svd->GetData(0);
+
+			// Measure the energy of both channels
+			// Samples are interleaved [l,r]
+			double l = 0, r = 0;
+			int sz = svd->GetInfo(0)->frameSize;
+			for( int i = 0 ; i != sz ; i++){
+				l += abs( d[2*i]);
+				r += abs( d[2*i+1]);
+			}
+
+			// If there is sufficient energy coming in
+			if( l+r > sz*1000.){
+				MMAccessor<HeadPointerMC> mc(mc_id);
+				double cur = state->outputs[ERS7Info::HeadOffset+1];
+				if( r > 1.3*l)
+					// Move your head righward
+					mc->setJoints( 0, cur-.2*M_PI/(r/l), 0);
+				if( l > 1.3*r)
+					// Move your head leftward
+					mc->setJoints( 0, cur+.2*M_PI/(l/r), 0);
+			}
+		}
+	}
+
+	virtual std::string getName() const { return "LookForSoundBehavior"; }
+
+	static std::string getClassDescription() { return "Looking for Sound Behavior Class"; }
+	
+protected:
+	MotionManager::MC_ID mc_id;
+};
+
+#endif
Index: Behaviors/Demos/MCRepeater.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/MCRepeater.h,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- Behaviors/Demos/MCRepeater.h	18 Jan 2004 10:16:56 -0000	1.2
+++ Behaviors/Demos/MCRepeater.h	17 Oct 2004 01:16:10 -0000	1.4
@@ -15,18 +15,18 @@
 
 	virtual void DoStart() {
 		BehaviorBase::DoStart(); // do this first
-		MotionManager::MC_ID id=motman->addMotion(*mc,true);
+		MotionManager::MC_ID id=motman->addPrunableMotion(*mc);
 		erouter->addListener(this,EventBase::motmanEGID,id,EventBase::deactivateETID);
 	}
 
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		BehaviorBase::DoStop(); // do this last
 	}
 
 	virtual void processEvent(const EventBase& /*e*/) {
-		erouter->forgetListener(this);
-		MotionManager::MC_ID id=motman->addMotion(*mc,true);
+		erouter->removeListener(this);
+		MotionManager::MC_ID id=motman->addPrunableMotion(*mc);
 		erouter->addListener(this,EventBase::motmanEGID,id,EventBase::deactivateETID);
 	}
 
@@ -48,9 +48,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.4 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/MotionStressTestBehavior.h
===================================================================
RCS file: Behaviors/Demos/MotionStressTestBehavior.h
diff -N Behaviors/Demos/MotionStressTestBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/MotionStressTestBehavior.h	17 Oct 2004 01:16:10 -0000	1.3
@@ -0,0 +1,97 @@
+//-*-c++-*-
+#ifndef INCLUDED_MotionStressTestBehavior_h_
+#define INCLUDED_MotionStressTestBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/MotionManager.h"
+#include "Motion/MotionSequenceMC.h"
+#include <queue>
+
+
+//! uses a separate MotionCommand for each of several joints to test for region leaks
+class MotionStressTestBehavior : public BehaviorBase {
+public:
+	//! constructor
+	MotionStressTestBehavior() : BehaviorBase(), nextLeg(RBkLegOrder), curMotions() {}
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+
+		SharedObject<MotionSequenceMC<MotionSequence::SizeSmall> > ms;
+		ms->setPlayTime(3000);
+		ms->setOutputCmd(LFrLegOffset+ElevatorOffset,outputRanges[LFrLegOffset+ElevatorOffset][MaxRange]);
+		ms->setOutputCmd(RFrLegOffset+ElevatorOffset,outputRanges[RFrLegOffset+ElevatorOffset][MaxRange]);
+		ms->setOutputCmd(LBkLegOffset+ElevatorOffset,outputRanges[LBkLegOffset+ElevatorOffset][MaxRange]);
+		ms->setOutputCmd(RBkLegOffset+ElevatorOffset,outputRanges[RBkLegOffset+ElevatorOffset][MaxRange]);
+		ms->setOutputCmd(LFrLegOffset+KneeOffset,0);
+		ms->setOutputCmd(RFrLegOffset+KneeOffset,0);
+		ms->setOutputCmd(LBkLegOffset+KneeOffset,0);
+		ms->setOutputCmd(RBkLegOffset+KneeOffset,0);
+		for(unsigned int i=HeadOffset; i<HeadOffset+NumHeadJoints; i++)
+			ms->setOutputCmd(i,0);
+		MotionManager::MC_ID id=motman->addPrunableMotion(ms);
+		curMotions.push(id);
+		cout << get_time() << "\tAdded id " << id << endl;
+		addMS(LFrLegOrder,3000);
+		addMS(RFrLegOrder,4000);
+		addMS(LBkLegOrder,5000);
+		erouter->addListener(this,EventBase::motmanEGID);
+	}
+
+	virtual void DoStop() {
+		erouter->removeListener(this);
+		while(!curMotions.empty()) {
+			motman->removeMotion(curMotions.front());
+			curMotions.pop();
+		}
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e.getTypeID()==EventBase::deactivateETID) {
+			if(e.getSourceID()!=curMotions.front()) {
+				cout << e.getSourceID() << " is not mine or is out of order" << endl;
+			} else {
+				curMotions.pop();
+			}
+			cout << get_time() << "\t              Removed id " << e.getSourceID() << endl;
+			addMS(nextLeg,3000);
+			nextLeg=static_cast<LegOrder_t>((nextLeg+1)%4);
+		}
+	}
+
+	void addMS(LegOrder_t leg,unsigned int delay=0) {
+		unsigned int index=leg*JointsPerLeg+RotatorOffset;
+		SharedObject<MotionSequenceMC<MotionSequence::SizeSmall> > ms;
+		ms->setPlayTime(delay);
+		ms->setOutputCmd(index,outputRanges[index][MaxRange]);
+		ms->setPlayTime(delay+2000);
+		ms->setOutputCmd(index,outputRanges[index][MinRange]);
+		ms->setPlayTime(delay+4000);
+		ms->setOutputCmd(index,outputRanges[index][MaxRange]);
+		MotionManager::MC_ID id=motman->addPrunableMotion(ms);
+		curMotions.push(id);
+		cout << get_time() << "\tAdded id " << id << endl;
+	}
+
+	virtual std::string getName() const { return "MotionStressTestBehavior"; }
+
+	static std::string getClassDescription() { return "uses a separate MotionCommand for each of several joints to test for region leaks"; }
+	
+protected:
+	LegOrder_t nextLeg;
+	std::queue<MotionManager::MC_ID> curMotions;
+};
+
+/*! @file
+ * @brief Defines MotionStressTestBehavior, which uses a separate MotionCommand for each of several joints to test for region leaks
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.3 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Demos/RelaxBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/RelaxBehavior.h,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- Behaviors/Demos/RelaxBehavior.h	18 Jan 2004 10:16:56 -0000	1.3
+++ Behaviors/Demos/RelaxBehavior.h	17 Oct 2004 01:16:10 -0000	1.5
@@ -27,13 +27,13 @@
 
 		// You could also change the priority level so that anytime
 		// a joint is not in use it goes limp (try kBackgroundPriority)
-		pidMCID=motman->addMotion(pidMC,MotionManager::kHighPriority,false);
+		pidMCID=motman->addPersistentMotion(pidMC,MotionManager::kHighPriority);
 		// the 'false' is to keep it from auto-pruning
 	}
 	virtual void DoStop() {
 		motman->removeMotion(pidMCID);
 		//this "one-shot" version of doing things will restore the PIDs
-		motman->addMotion(SharedObject<PIDMC>(1));
+		motman->addPrunableMotion(SharedObject<PIDMC>(1));
 		BehaviorBase::DoStop();
 	}
 	virtual std::string getName() const { return "RelaxBehavior"; }
@@ -50,7 +50,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/17 01:16:10 $
  */
Index: Behaviors/Demos/SimpleChaseBallBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/SimpleChaseBallBehavior.h,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- Behaviors/Demos/SimpleChaseBallBehavior.h	5 Dec 2003 20:26:34 -0000	1.6
+++ Behaviors/Demos/SimpleChaseBallBehavior.h	17 Oct 2004 01:16:10 -0000	1.9
@@ -27,13 +27,13 @@
 	//! adds a headpointer and a walker, and a listens for vision events
 	virtual void DoStart() {
 		BehaviorBase::DoStart();
-		walker_id = motman->addMotion(SharedObject<WalkMC>());
+		walker_id = motman->addPersistentMotion(SharedObject<WalkMC>()); //the 'false' prevents autopruning
 		erouter->addListener(this,EventBase::visObjEGID);
 	}
 
 	//! removes motion commands and stops listening
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		motman->removeMotion(walker_id);
 		BehaviorBase::DoStop();
 	}
@@ -61,9 +61,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2003/12/05 20:26:34 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/StareAtBallBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/StareAtBallBehavior.cc,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- Behaviors/Demos/StareAtBallBehavior.cc	9 Dec 2003 17:33:14 -0000	1.6
+++ Behaviors/Demos/StareAtBallBehavior.cc	17 Oct 2004 01:16:10 -0000	1.9
@@ -10,12 +10,12 @@
 
 void StareAtBallBehavior::DoStart() {
 	BehaviorBase::DoStart();
-	headpointer_id = motman->addMotion(SharedObject<HeadPointerMC>());
+	headpointer_id = motman->addPersistentMotion(SharedObject<HeadPointerMC>());
 	erouter->addListener(this,EventBase::visObjEGID,ProjectInterface::visPinkBallSID);
 }
 
 void StareAtBallBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	motman->removeMotion(headpointer_id);
 	BehaviorBase::DoStop();
 }
Index: Behaviors/Demos/StareAtPawBehavior.h
===================================================================
RCS file: Behaviors/Demos/StareAtPawBehavior.h
diff -N Behaviors/Demos/StareAtPawBehavior.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/StareAtPawBehavior.h	17 Oct 2004 01:16:10 -0000	1.5
@@ -0,0 +1,102 @@
+//-*-c++-*-
+#ifndef INCLUDED_StareAtPawBehavior_h_
+#define INCLUDED_StareAtPawBehavior_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/OldKinematics.h"
+#include "Motion/PIDMC.h"
+#include "Motion/HeadPointerMC.h"
+#include "Motion/MotionManager.h"
+#include "Shared/SharedObject.h"
+
+
+//! Uses kinematics to track the paw which last received a button press with the camera
+class StareAtPawBehavior : public BehaviorBase {
+public:
+	//! constructor
+	StareAtPawBehavior()
+		: BehaviorBase(), lastLeg(LFrLegOrder), pointID(MotionManager::invalid_MC_ID)
+	{ }
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		for(unsigned int i=0; i<NumHeadJoints; i++)
+			head_angles[i]=state->outputs[HeadOffset+i];
+		pointID=motman->addPersistentMotion(SharedObject<HeadPointerMC>());
+		erouter->addListener(this,EventBase::sensorEGID);
+		erouter->addListener(this,EventBase::buttonEGID);
+	}
+
+	virtual void DoStop() {
+		motman->removeMotion(pointID);
+		pointID=MotionManager::invalid_MC_ID;
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e.getGeneratorID()==EventBase::buttonEGID) {
+
+			if(e.getSourceID()==LFrPawOffset)
+				lastLeg=LFrLegOrder;
+			else if(e.getSourceID()==RFrPawOffset)
+				lastLeg=RFrLegOrder;
+			else
+				return;
+			if(e.getTypeID()==EventBase::activateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> relaxLeg(lastlegoff,lastlegoff+JointsPerLeg,0);
+				motman->addPrunableMotion(relaxLeg);
+			} else if(e.getTypeID()==EventBase::deactivateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> tightLeg(lastlegoff,lastlegoff+JointsPerLeg,1);
+				motman->addPrunableMotion(tightLeg);
+			}
+
+		} else if(e.getGeneratorID()==EventBase::sensorEGID) {
+
+			double leg_angles[JointsPerLeg];
+			for(unsigned int i=0; i<JointsPerLeg; i++)
+				leg_angles[i]=state->outputs[LegOffset+lastLeg*JointsPerLeg+i];
+			vector3d paw;
+			GetLegPosition(paw,leg_angles,lastLeg);
+			paw-=body_to_neck; //target should be neck-relative
+			paw.z+=body_to_neck.z; // but body-height relative (#@%&$)
+			GetHeadAngles(head_angles,paw,0,0);
+			/*{
+				double tmp[JointsPerLeg];
+				GetLegAngles(tmp,paw,lastLeg);
+				sout->printf("Leg: (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n",leg_angles[0],leg_angles[1],leg_angles[2],paw.x,paw.y,paw.z,tmp[0],tmp[1],tmp[2]);
+				vector3d tmp2;
+				tmp2=RunForwardModel(head_angles,0,0,vector3d(0,0,0));
+				sout->printf("Head: (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n",tmp2.x,tmp2.y,tmp2.z,head_angles[0],head_angles[1],head_angles[2],state->outputs[HeadOffset+0],state->outputs[HeadOffset+1],state->outputs[HeadOffset+2]);
+				}*/
+			MMAccessor<HeadPointerMC>(pointID)->setJoints(head_angles[0],head_angles[1],head_angles[2]);
+			
+		} else {
+			serr->printf("StareAtPawBehavior: Unhandled event %s\n",e.getName().c_str());
+		}
+	}
+
+	virtual std::string getName() const { return "StareAtPawBehavior"; }
+
+	static std::string getClassDescription() { return "Uses kinematics to track the paw which last received a button press with the camera"; }
+	
+protected:
+	LegOrder_t lastLeg;
+	MotionManager::MC_ID pointID;
+	double head_angles[JointsPerLeg];
+};
+
+/*! @file
+ * @brief Defines StareAtPawBehavior, which uses kinematics to track the paw which last received a button press with the camera
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.5 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Demos/StareAtPawBehavior2.h
===================================================================
RCS file: Behaviors/Demos/StareAtPawBehavior2.h
diff -N Behaviors/Demos/StareAtPawBehavior2.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Demos/StareAtPawBehavior2.h	17 Oct 2004 01:32:24 -0000	1.12
@@ -0,0 +1,102 @@
+//-*-c++-*-
+#ifndef INCLUDED_StareAtPawBehavior2_h_
+#define INCLUDED_StareAtPawBehavior2_h_
+
+#include "Behaviors/BehaviorBase.h"
+#include "Motion/PIDMC.h"
+#include "Motion/HeadPointerMC.h"
+#include "Motion/PostureMC.h"
+#include "Motion/MotionManager.h"
+#include "Shared/SharedObject.h"
+#include "Motion/roboop/robot.h"
+#include "Shared/Config.h"
+#include "Motion/Kinematics.h"
+
+
+//! Uses kinematics to track the paw which last received a button press with the camera
+class StareAtPawBehavior2 : public BehaviorBase {
+public:
+	//! constructor
+	StareAtPawBehavior2()
+		: BehaviorBase(), lastLeg(LFrLegOrder), pointID(MotionManager::invalid_MC_ID)
+	{ }
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		pointID=motman->addPersistentMotion(SharedObject<HeadPointerMC>());
+		erouter->addListener(this,EventBase::sensorEGID);
+		erouter->addListener(this,EventBase::buttonEGID);
+		if(state->robotDesign == WorldState::ERS7Mask)
+			cout << "NOTICE: The ERS-7 has a rather \"sticky\" nod joint\n"
+					 << "(the upper tilt joint).  This can cause it to hesitate\n"
+					 << "or altogether fail to precisely center the target position\n"
+					 << "vertically in the center of the image...\n" << endl;
+	}
+
+	virtual void DoStop() {
+		motman->removeMotion(pointID);
+		pointID=MotionManager::invalid_MC_ID;
+		erouter->removeListener(this);
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		if(e.getGeneratorID()==EventBase::buttonEGID) {
+
+			if(e.getSourceID()==LFrPawOffset) {
+				lastLeg=LFrLegOrder;
+			} else if(e.getSourceID()==RFrPawOffset) {
+				lastLeg=RFrLegOrder;
+			} else
+				return;
+			if(e.getTypeID()==EventBase::activateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> relaxLeg(lastlegoff,lastlegoff+JointsPerLeg,0);
+				motman->addPrunableMotion(relaxLeg);
+			} else if(e.getTypeID()==EventBase::deactivateETID) {
+				unsigned int lastlegoff=LegOffset+lastLeg*JointsPerLeg;
+				SharedObject<PIDMC> tightLeg(lastlegoff,lastlegoff+JointsPerLeg,1);
+				motman->addPrunableMotion(tightLeg);
+			}
+
+		} else if(e.getGeneratorID()==EventBase::sensorEGID) {
+
+			//Find paw location
+			const char * ipname=(lastLeg==LFrLegOrder?"ToeLFrPaw":"ToeRFrPaw");
+			NEWMAT::ColumnVector Pobj=kine->getFrameInterestPoint(BaseFrameOffset,ipname);
+
+			//Compute neck angles
+			PostureEngine pose;
+			NEWMAT::ColumnVector Plink(4); Plink=0; Plink(3)=1; //infinite ray along z axis, maximizes distance from camera to objective
+			//NEWMAT::ColumnVector Plink(4); Plink=0; Plink(3)=80; Plink(4)=1; //keep head 8cm away from paw
+			//Alternatively, could also use the pack function a la: Plink=Kinematics::pack(0,0,80);
+			pose.solveLinkVector(Pobj,CameraFrameOffset,Plink);
+			
+			//Set joint values
+			MMAccessor<HeadPointerMC>(pointID)->setJoints(pose(HeadOffset+0).value,pose(HeadOffset+1).value,pose(HeadOffset+2).value);
+		} else {
+			serr->printf("StareAtPawBehavior2: Unhandled event %s\n",e.getName().c_str());
+		}
+	}
+
+	virtual std::string getName() const { return "StareAtPawBehavior2"; }
+
+	static std::string getClassDescription() { return "Uses kinematics to track the paw which last received a button press with the camera"; }
+	
+protected:
+	LegOrder_t lastLeg;
+	MotionManager::MC_ID pointID;
+};
+
+/*! @file
+ * @brief Defines StareAtPawBehavior2, which uses kinematics to track the paw which last received a button press with the camera
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.12 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:32:24 $
+ */
+
+#endif
Index: Behaviors/Demos/ToggleHeadLightBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/ToggleHeadLightBehavior.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Behaviors/Demos/ToggleHeadLightBehavior.h	2 Sep 2003 20:58:49 -0000	1.2
+++ Behaviors/Demos/ToggleHeadLightBehavior.h	17 Oct 2004 01:16:10 -0000	1.3
@@ -18,7 +18,7 @@
 		if(state->robotDesign & WorldState::ERS220Mask) {
 			SharedObject<PostureMC> pose;
 			pose->setOutputCmd(ERS220Info::RetractableHeadLEDOffset,true);
-			light_id=motman->addMotion(pose,false);
+			light_id=motman->addPersistentMotion(pose);
 		}
 	}
 
@@ -41,9 +41,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
- * $State: Rel $
- * $Date: 2003/09/02 20:58:49 $
+ * $Revision: 1.3 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Demos/WalkToTargetMachine.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/WalkToTargetMachine.cc,v
retrieving revision 1.10
retrieving revision 1.14
diff -u -d -r1.10 -r1.14
--- Behaviors/Demos/WalkToTargetMachine.cc	5 Dec 2003 20:26:34 -0000	1.10
+++ Behaviors/Demos/WalkToTargetMachine.cc	17 Oct 2004 01:16:10 -0000	1.14
@@ -18,15 +18,21 @@
 
 void WalkToTargetMachine::DoStart() {
 	StateNode::DoStart();
-	headpointer_id = motman->addMotion(SharedObject<HeadPointerMC>());
-	walker_id = motman->addMotion(SharedObject<WalkMC>());
+
+	headpointer_id = motman->addPersistentMotion(SharedObject<HeadPointerMC>());
+	walker_id = motman->addPersistentMotion(SharedObject<WalkMC>());
+
 	erouter->addListener(this,EventBase::visObjEGID,tracking);
 }
 
 void WalkToTargetMachine::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
+
 	motman->removeMotion(headpointer_id);
+	headpointer_id=MotionManager::invalid_MC_ID;
 	motman->removeMotion(walker_id);
+	walker_id=MotionManager::invalid_MC_ID;
+
 	StateNode::DoStop();
 }
 
@@ -77,8 +83,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
+ * $Revision: 1.14 $
  * $State: Exp $
- * $Date: 2003/12/05 20:26:34 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Demos/WorldStateVelDaemon.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Demos/WorldStateVelDaemon.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Behaviors/Demos/WorldStateVelDaemon.h	18 Jan 2004 10:16:56 -0000	1.2
+++ Behaviors/Demos/WorldStateVelDaemon.h	7 Oct 2004 19:07:04 -0000	1.3
@@ -28,7 +28,7 @@
 	}
 
 	virtual void DoStop() {
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		BehaviorBase::DoStop(); // do this last
 	}
 
@@ -87,9 +87,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
 #endif
Index: Behaviors/Mon/Aibo3DControllerBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/Aibo3DControllerBehavior.h,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- Behaviors/Mon/Aibo3DControllerBehavior.h	18 Jan 2004 10:16:56 -0000	1.3
+++ Behaviors/Mon/Aibo3DControllerBehavior.h	17 Oct 2004 01:16:10 -0000	1.5
@@ -78,7 +78,7 @@
 		for(unsigned int i=0; i<NumPIDJoints; i++)
 			val[i]=state->outputs[i];
 		// Enable remote control stream
-		rcontrol_id = motman->addMotion(SharedObject<RemoteControllerMC>());
+		rcontrol_id = motman->addPersistentMotion(SharedObject<RemoteControllerMC>());
 		updateRC();
 		// Turn on wireless
 		cmdsock=wireless->socket(SocketNS::SOCK_STREAM, 2048, 2048);
@@ -131,9 +131,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:56 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif 
Index: Behaviors/Mon/EStopControllerBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/EStopControllerBehavior.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Behaviors/Mon/EStopControllerBehavior.cc	14 Jan 2004 20:44:31 -0000	1.3
+++ Behaviors/Mon/EStopControllerBehavior.cc	7 Oct 2004 19:07:04 -0000	1.4
@@ -18,7 +18,7 @@
 
 void EStopControllerBehavior::DoStop() {
 	// Turn off timers
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	// Close socket; turn wireless off
   wireless->setDaemon(cmdsock,false);
 	wireless->close(cmdsock);
@@ -73,8 +73,8 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * $State: Exp $
- * $Date: 2004/01/14 20:44:31 $
+ * $Date: 2004/10/07 19:07:04 $
  */
 
Index: Behaviors/Mon/HeadPointControllerBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc,v
retrieving revision 1.4
retrieving revision 1.7
diff -u -d -r1.4 -r1.7
--- Behaviors/Mon/HeadPointControllerBehavior.cc	5 Feb 2004 01:51:39 -0000	1.4
+++ Behaviors/Mon/HeadPointControllerBehavior.cc	17 Oct 2004 01:16:10 -0000	1.7
@@ -1,6 +1,7 @@
 #include "HeadPointControllerBehavior.h"
 #include "Behaviors/Controller.h"
 #include "Motion/MMAccessor.h"
+#include "Motion/HeadPointerMC.h"
 
 HeadPointControllerBehavior* HeadPointControllerBehavior::theOne = NULL;
 
@@ -55,7 +56,7 @@
 	// We listen to timers
 	erouter->addListener(this, EventBase::timerEGID);
 	// Enable head control
-	head_id = motman->addMotion(SharedObject<HeadPointerMC>());
+	head_id = motman->addPersistentMotion(SharedObject<HeadPointerMC>());
 	// Turn on wireless
 	theLastOne=theOne;
 	theOne=this;
@@ -71,7 +72,7 @@
 	// Close the GUI
 	Controller::closeGUI("HeadPointGUI");
 	// Turn off timers
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	// Close socket; turn wireless off
 	wireless->setDaemon(cmdsock,false);
 	wireless->close(cmdsock);
@@ -124,8 +125,8 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2004/02/05 01:51:39 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Mon/HeadPointControllerBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Behaviors/Mon/HeadPointControllerBehavior.h	11 Dec 2003 05:49:30 -0000	1.2
+++ Behaviors/Mon/HeadPointControllerBehavior.h	14 Oct 2004 21:59:14 -0000	1.3
@@ -6,7 +6,6 @@
 #include "Wireless/Wireless.h"
 #include "Behaviors/BehaviorBase.h"
 #include "Motion/MotionManager.h"
-#include "Motion/HeadPointerMC.h"
 #include "Events/EventRouter.h"
 #include "Events/EventBase.h"
 #include "Shared/Config.h"
@@ -84,9 +83,9 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * $State: Exp $
- * $Date: 2003/12/11 05:49:30 $
+ * $Date: 2004/10/14 21:59:14 $
  */
 
 #endif 
Index: Behaviors/Mon/RawCamBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/RawCamBehavior.cc,v
retrieving revision 1.10
retrieving revision 1.13
diff -u -d -r1.10 -r1.13
--- Behaviors/Mon/RawCamBehavior.cc	5 Feb 2004 19:11:26 -0000	1.10
+++ Behaviors/Mon/RawCamBehavior.cc	7 Oct 2004 19:07:05 -0000	1.13
@@ -8,17 +8,30 @@
 #include "Shared/ProjectInterface.h"
 
 RawCamBehavior::RawCamBehavior()
-	: BehaviorBase(), visRaw(NULL), packet(NULL), cur(NULL), avail(0)
+	: BehaviorBase(), visRaw(NULL), packet(NULL), cur(NULL), avail(0), max_buf(0)
 {}
 
 void
 RawCamBehavior::DoStart() {
 	BehaviorBase::DoStart();
-  visRaw=wireless->socket(SocketNS::SOCK_STREAM, 1024, WIRELESS_BUFFER_SIZE);
-  wireless->setDaemon(visRaw,true);
-  wireless->listen(visRaw,config->vision.rawcam_port);
 	
-	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","RawVisionGUI",config->vision.rawcam_port);
+	std::vector<std::string> args;
+	if(config->vision.rawcam_transport==0) {
+		max_buf=UDP_WIRELESS_BUFFER_SIZE;
+		visRaw=wireless->socket(SocketNS::SOCK_DGRAM, 1024, max_buf);
+		args.push_back("udp");
+	} else if(config->vision.rawcam_transport==1) {
+		max_buf=TCP_WIRELESS_BUFFER_SIZE;
+		visRaw=wireless->socket(SocketNS::SOCK_STREAM, 1024, max_buf);
+		wireless->setDaemon(visRaw,true);
+		args.push_back("tcp");
+	} else {
+		serr->printf("ERROR: Invalid Config::vision.rawcam_transport: %d\n",config->vision.rawcam_transport);
+		return;
+	}
+	wireless->listen(visRaw,config->vision.rawcam_port);
+	
+	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","RawVisionGUI",config->vision.rawcam_port,args);
 
 	erouter->addListener(this,EventBase::visRawCameraEGID,ProjectInterface::visRawCameraSID);
 	erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visColorJPEGSID);
@@ -27,12 +40,12 @@
 
 void
 RawCamBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	Controller::closeGUI("RawVisionGUI");
 
 	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
 	// it will try to listen again even though we explicitly closed the server socket...
-  wireless->setDaemon(visRaw,false);
+	wireless->setDaemon(visRaw,false);
 	wireless->close(visRaw->sock);
 	BehaviorBase::DoStop();
 }
@@ -62,7 +75,7 @@
 	if(packet!=NULL)
 		return false;
 
-	avail=WIRELESS_BUFFER_SIZE-1; //not sure why -1, but Alok had it, so i will too
+	avail=max_buf-1; //not sure why -1, but Alok had it, so i will too
 	ASSERT(cur==NULL,"cur non-NULL");
 	cur=NULL;
 	char * buf=packet=(char*)visRaw->getWriteBuffer(avail);
@@ -253,11 +266,19 @@
 	return true;
 }
 
+//#include "Shared/WorldState.h"
+
 void
 RawCamBehavior::closePacket() {
 	if(packet==NULL)
 		return;
 	visRaw->write(cur-packet);
+	/*	cout << "used=" << (cur-packet) << "\tavail==" << avail;
+	if(state->robotDesign & WorldState::ERS7Mask)
+		cout << "\tmax bandwidth=" << (cur-packet)/1024.f*30 << "KB/sec" << endl;
+	else
+		cout << "\tmax bandwidth=" << (cur-packet)/1024.f*24 << "KB/sec" << endl;
+	*/
 	packet=cur=NULL;
 	avail=0;
 }
@@ -269,8 +290,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
+ * $Revision: 1.13 $
  * $State: Exp $
- * $Date: 2004/02/05 19:11:26 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
Index: Behaviors/Mon/RawCamBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/RawCamBehavior.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- Behaviors/Mon/RawCamBehavior.h	5 Feb 2004 23:33:41 -0000	1.8
+++ Behaviors/Mon/RawCamBehavior.h	28 Sep 2004 22:12:30 -0000	1.9
@@ -33,7 +33,8 @@
 	//! constructor
 	RawCamBehavior();
 
-	static const unsigned int WIRELESS_BUFFER_SIZE=200000; //!< 200000 bytes for use up to 416x320 + 2*208x160 (double res Y, full res UV on ERS-7)
+	static const unsigned int TCP_WIRELESS_BUFFER_SIZE=200000; //!< 200000 bytes for use up to 416x320 + 2*208x160 (double res Y, full res UV on ERS-7)
+	static const unsigned int UDP_WIRELESS_BUFFER_SIZE=64*1024; //!< 64KB is the max udp packet size
 
 	virtual void DoStart();
 
@@ -61,6 +62,7 @@
 	char * packet; //!< point to the current buffer being prepared to be sent
 	char * cur; //!< current location within that buffer
 	unsigned int avail; //!< the number of bytes remaining in the buffer
+	unsigned int max_buf; //!< the buffer size requested from Wireless when the socket was allocated
 
 private:
 	RawCamBehavior(const RawCamBehavior&); //!< don't call
@@ -73,9 +75,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2004/02/05 23:33:41 $
+ * $Date: 2004/09/28 22:12:30 $
  */
 
 #endif
Index: Behaviors/Mon/SegCamBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/SegCamBehavior.cc,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- Behaviors/Mon/SegCamBehavior.cc	5 Feb 2004 19:11:26 -0000	1.6
+++ Behaviors/Mon/SegCamBehavior.cc	7 Oct 2004 19:07:05 -0000	1.9
@@ -8,18 +8,31 @@
 #include "Vision/RLEGenerator.h"
 
 SegCamBehavior::SegCamBehavior()
-	: BehaviorBase(), visRLE(NULL), packet(NULL), cur(NULL), avail(0)
+	: BehaviorBase(), visRLE(NULL), packet(NULL), cur(NULL), avail(0), max_buf(0)
 {
 }
 
 void
 SegCamBehavior::DoStart() {
 	BehaviorBase::DoStart();
-  visRLE=wireless->socket(SocketNS::SOCK_STREAM, 1024, WIRELESS_BUFFER_SIZE);
-  wireless->setDaemon(visRLE,true);
-  wireless->listen(visRLE,config->vision.rle_port);
+	
+	std::vector<std::string> args;
+	if(config->vision.rle_transport==0) {
+		max_buf=UDP_WIRELESS_BUFFER_SIZE;
+		visRLE=wireless->socket(SocketNS::SOCK_DGRAM, 1024, max_buf);
+		args.push_back("udp");
+	} else if(config->vision.rle_transport==1) {
+		max_buf=TCP_WIRELESS_BUFFER_SIZE;
+		visRLE=wireless->socket(SocketNS::SOCK_STREAM, 1024, max_buf);
+		wireless->setDaemon(visRLE,true);
+		args.push_back("tcp");
+	} else {
+		serr->printf("ERROR: Invalid Config::vision.rle_transport: %d\n",config->vision.rle_transport);
+		return;
+	}
+	wireless->listen(visRLE,config->vision.rle_port);
 
-	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","SegVisionGUI",config->vision.rle_port);
+	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","SegVisionGUI",config->vision.rle_port,args);
 
 	erouter->addListener(this,EventBase::visSegmentEGID,ProjectInterface::visSegmentSID);
 	erouter->addListener(this,EventBase::visRLEEGID,ProjectInterface::visRLESID);
@@ -27,12 +40,12 @@
 
 void
 SegCamBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	Controller::closeGUI("SegVisionGUI");
 
 	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
 	// it will try to listen again even though we explicitly closed the server socket...
-  wireless->setDaemon(visRLE,false);
+	wireless->setDaemon(visRLE,false);
 	wireless->close(visRLE->sock);
 	BehaviorBase::DoStop();
 }
@@ -58,7 +71,7 @@
 	if(packet!=NULL)
 		return false;
 
-	avail=WIRELESS_BUFFER_SIZE-1; //not sure why -1, but Alok had it, so i will too
+	avail=max_buf-1; //not sure why -1, but Alok had it, so i will too
 	ASSERT(cur==NULL,"cur non-NULL");
 	cur=NULL;
 	char * buf=packet=(char*)visRLE->getWriteBuffer(avail);
@@ -155,8 +168,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2004/02/05 19:11:26 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
Index: Behaviors/Mon/SegCamBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/SegCamBehavior.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Behaviors/Mon/SegCamBehavior.h	5 Feb 2004 23:33:41 -0000	1.5
+++ Behaviors/Mon/SegCamBehavior.h	28 Sep 2004 22:12:30 -0000	1.6
@@ -44,7 +44,8 @@
 	//! constructor
 	SegCamBehavior();
 
-	static const unsigned int WIRELESS_BUFFER_SIZE=85000; //!< 85000 bytes for use up to 416x320 pixels / 8 min expected runs * 5 bytes per run + some padding
+	static const unsigned int TCP_WIRELESS_BUFFER_SIZE=85000; //!< 85000 bytes for use up to 416x320 pixels / 8 min expected runs * 5 bytes per run + some padding
+	static const unsigned int UDP_WIRELESS_BUFFER_SIZE=64*1024; //!< 64KB is the max udp packet size
 
 	virtual void DoStart();
 
@@ -72,6 +73,7 @@
 	char * packet; //!< buffer being filled out to be sent
 	char * cur; //!< current location in #packet
 	unsigned int avail; //!< number of bytes remaining in #packet
+	unsigned int max_buf; //!< the buffer size requested from Wireless when the socket was allocated
 
 private:
 	SegCamBehavior(const SegCamBehavior&); //!< don't call
@@ -84,9 +86,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
  * $State: Exp $
- * $Date: 2004/02/05 23:33:41 $
+ * $Date: 2004/09/28 22:12:30 $
  */
 
 #endif
Index: Behaviors/Mon/ViewWMVarsBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/ViewWMVarsBehavior.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Behaviors/Mon/ViewWMVarsBehavior.h	10 Oct 2003 00:47:52 -0000	1.1
+++ Behaviors/Mon/ViewWMVarsBehavior.h	16 Apr 2004 20:17:22 -0000	1.2
@@ -7,7 +7,7 @@
 #include "Shared/Config.h"
 #include <stdio.h>
 
-//! simply launches the Watchable Memory GUI
+//! simply launches the Watchable Memory GUI, which should connect to the already-running WMMonitorBehavior
 class ViewWMVarsBehavior : public BehaviorBase {
 public:
 	//! constructor
@@ -29,19 +29,19 @@
 	static std::string getClassDescription() {
 		char tmp[20];
 		sprintf(tmp,"%d",config->main.wmmonitor_port);
-		return std::string("Brings up the WatchableMemory GUI on port ")+tmp;
+		return std::string("Brings up the WatchableMemory GUI on port ")+tmp+std::string(" (connects to WMMonitorBehavior, this just launches the GUI)");
 	}
 };
 
 /*! @file
- * @brief Describes ViewWMVarsBehavior, simply launches the Watchable Memory GUI
+ * @brief Defines ViewWMVarsBehavior, simply launches the Watchable Memory GUI, which should connect to the already-running WMMonitorBehavior
  * @author ejt (Creator)
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.1 $
- * $State: Rel $
- * $Date: 2003/10/10 00:47:52 $
+ * $Revision: 1.2 $
+ * $State: Exp $
+ * $Date: 2004/04/16 20:17:22 $
  */
 
 #endif 
Index: Behaviors/Mon/WMMonitorBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/WMMonitorBehavior.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Behaviors/Mon/WMMonitorBehavior.cc	19 Jan 2004 20:35:31 -0000	1.2
+++ Behaviors/Mon/WMMonitorBehavior.cc	16 Apr 2004 20:17:22 -0000	1.3
@@ -26,15 +26,20 @@
           wmitem->toString());
   } else if (cmd[0]=='r') {
     WMregistry* wmreg=NULL;
-    if (var.length()==0) wmreg=&GlobalWM;
+    if (var.length()==0)
+			wmreg=&GlobalWM;
     else {
       WMitem<WMregistry>* wmitem=static_cast<WMitem<WMregistry> *> (find (var));
       if (wmitem!=NULL)
         wmreg=&wmitem->get_value();
+			else
+				serr->printf("WMMonitorBehavior: Could not find '%s'\n",var.c_str());
     }
-    if (wmreg!=NULL)
-      for (std::vector<WMentry*>::const_iterator it = wmreg->entries.begin();
-          it != wmreg->entries.end(); it++) {
+    if (wmreg==NULL)
+			serr->printf("WMMonitorBehavior: wmreg is NULL\n");
+		else {
+			//sout->printf("Reporting:\n");
+      for (std::vector<WMentry*>::const_iterator it = wmreg->entries.begin(); it != wmreg->entries.end(); it++) {
         WMentry* entry=*it;
         std::string sn(entry->item_name);
         WMregistry *temp=entry->registry;
@@ -42,8 +47,10 @@
           sn=temp->name + "." + sn;
           temp=temp->parent;
         }
+				//sout->printf("Reporting %s %s %s\n",entry->type_name.c_str(),sn.c_str(),entry->item->toString().c_str());
         report(entry->type_name, sn, entry->item->toString());
       }
+		}
   } else if (cmd[0]=='d') {    // set debug mode (blocking/nonblocking)
     // implement within this class
   }
@@ -98,9 +105,7 @@
 WMMonitorBehavior::report (const char* var_type, int var_type_length,
                            const char* var_name, int var_name_length,
                            const char* value, int value_length) {
-  char *buf=(char*)cmdsock->getWriteBuffer(5+ var_type_length+
-                                              var_name_length+
-                                              value_length);
+  char *buf=(char*)cmdsock->getWriteBuffer(5*sizeof(int)+var_type_length+var_name_length+value_length);
   if (buf) {
     encodeHeader(&buf, packet_wmclass);
     encode(&buf, var_type_length);
@@ -110,7 +115,8 @@
     encode(&buf, value_length);
     encode(&buf, value, value_length);
     cmdsock->write(5*sizeof(int)+var_type_length+var_name_length+value_length);
-  }
+  } else
+		serr->printf("WMMonitorBehavior: Failed to get write buffer\n");
 }
 
 int wmmonitorcmd_callback(char *buf, int bytes) {
@@ -141,7 +147,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * $State: Exp $
- * $Date: 2004/01/19 20:35:31 $
+ * $Date: 2004/04/16 20:17:22 $
  */
Index: Behaviors/Mon/WMMonitorBehavior.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/WMMonitorBehavior.h,v
retrieving revision 1.6
retrieving revision 1.8
diff -u -d -r1.6 -r1.8
--- Behaviors/Mon/WMMonitorBehavior.h	19 Jan 2004 20:35:31 -0000	1.6
+++ Behaviors/Mon/WMMonitorBehavior.h	7 Oct 2004 19:07:05 -0000	1.8
@@ -77,7 +77,7 @@
 
 	virtual void DoStop() {
 //		Controller::closeGUI(getGUIType());
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		// Close socket; turn wireless off
 		wireless->setDaemon(cmdsock,false); 
 		wireless->close(cmdsock);
@@ -106,7 +106,7 @@
 	}
 
 protected:
-	static const unsigned int packet_wmclass=12; //!< magic id number
+	static const unsigned int packet_wmclass=14; //!< magic id number, corresponds to Listener.java PACKET_WMCLASS
   //! writes packet type and timestamp
   inline static void encodeHeader(char **dst, unsigned int pformat) {
     encode(dst, pformat);
@@ -137,9 +137,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2004/01/19 20:35:31 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
 #endif 
Index: Behaviors/Mon/WalkControllerBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/WalkControllerBehavior.cc,v
retrieving revision 1.3
retrieving revision 1.6
diff -u -d -r1.3 -r1.6
--- Behaviors/Mon/WalkControllerBehavior.cc	19 Jan 2004 19:43:51 -0000	1.3
+++ Behaviors/Mon/WalkControllerBehavior.cc	17 Oct 2004 01:16:10 -0000	1.6
@@ -87,7 +87,7 @@
 	// We listen to timers
 	erouter->addListener(this, EventBase::timerEGID);
 	// Enable walker (the MC_ID can be accessed through the shared_walker later)
-	motman->addMotion(shared_walker);
+	motman->addPersistentMotion(shared_walker);
 	// Turn on wireless
 	theLastOne=theOne;
 	theOne=this;
@@ -103,7 +103,7 @@
 	// Close the GUI
 	Controller::closeGUI("WalkGUI");
 	// Turn off timers
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	// Close socket; turn wireless off
 	wireless->setDaemon(cmdsock,false); 
 	wireless->close(cmdsock);
@@ -158,8 +158,8 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.6 $
  * $State: Exp $
- * $Date: 2004/01/19 19:43:51 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Behaviors/Mon/WorldStateSerializerBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Behaviors/Mon/WorldStateSerializerBehavior.cc	24 Jan 2004 21:28:50 -0000	1.2
+++ Behaviors/Mon/WorldStateSerializerBehavior.cc	7 Oct 2004 19:07:05 -0000	1.3
@@ -21,7 +21,7 @@
 }
 
 void WorldStateSerializerBehavior::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	BehaviorBase::DoStop(); // do this last
 }
 
@@ -54,7 +54,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * $State: Exp $
- * $Date: 2004/01/24 21:28:50 $
+ * $Date: 2004/10/07 19:07:05 $
  */
Index: Behaviors/Nodes/HeadPointerNode.h
===================================================================
RCS file: Behaviors/Nodes/HeadPointerNode.h
diff -N Behaviors/Nodes/HeadPointerNode.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Nodes/HeadPointerNode.h	17 Oct 2004 01:16:10 -0000	1.2
@@ -0,0 +1,60 @@
+//-*-c++-*-
+#ifndef INCLUDED_HeadPointerNode_h_
+#define INCLUDED_HeadPointerNode_h_
+
+#include "Behaviors/StateNode.h"
+#include "Events/EventRouter.h"
+#include "Motion/HeadPointerMC.h"
+
+//! A simple StateNode that executes a LedMC motion command and throws a status event upon completion
+class HeadPointerNode : public StateNode {
+protected:
+  SharedObject<HeadPointerMC> head_mc;    //!< MotionCommand used by this node
+  MotionManager::MC_ID head_id;  //!< id number for the MotionCommand
+
+public:
+  //! constructor
+  HeadPointerNode(std::string nodename="HeadPointerNode") : 
+    StateNode(nodename), head_mc(), head_id(MotionManager::invalid_MC_ID) {}
+
+  //! activate the node
+  virtual void DoStart() {
+    head_id = motman->addPersistentMotion(head_mc);
+    erouter->addListener(this,EventBase::motmanEGID,head_id,EventBase::statusETID);
+    StateNode::DoStart();  // don't activate transitions until our listener has been added
+  }
+
+  //! deactivate the node
+  virtual void DoStop() {
+    motman->removeMotion(head_id);
+    head_id = MotionManager::invalid_MC_ID;
+    erouter->removeListener(this);
+    StateNode::DoStop();
+  }
+
+  //! receive motmanEGID status event and throw stateMachineEGID status event
+  virtual void processEvent(const EventBase&) {
+    erouter->postEvent(EventBase::stateMachineEGID,(unsigned int)this,EventBase::statusETID,0);
+  }
+
+  //! reveal the MotionCommand
+  SharedObject<HeadPointerMC>& getMC() { return head_mc; }
+
+  //! reveal the MC_ID
+  MotionManager::MC_ID& getMC_ID() { return head_id; }
+
+
+};
+
+/*! @file
+ * @brief Defines HeadPointerNode, a simple StateNode that runs a HeadPointerMC motion command and throws a status event upon completion
+ * @author dst (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.2 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Nodes/PlayMotionSequenceNode.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Nodes/PlayMotionSequenceNode.h,v
retrieving revision 1.2
retrieving revision 1.6
diff -u -d -r1.2 -r1.6
--- Behaviors/Nodes/PlayMotionSequenceNode.h	18 Jan 2004 10:16:57 -0000	1.2
+++ Behaviors/Nodes/PlayMotionSequenceNode.h	17 Oct 2004 01:16:10 -0000	1.6
@@ -35,7 +35,7 @@
 
 	virtual void DoStop() {
 		//std::cout << "PlayMotionSequenceNode::DoStop(); " << std::endl;
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		motman->removeMotion(msid);
 		msid=MotionManager::invalid_MC_ID;
 		StateNode::DoStop();
@@ -78,6 +78,7 @@
 			if(looping) {
 				updateMS(filename);
 			}
+			erouter->postEvent(EventBase::stateMachineEGID,(unsigned int)this,EventBase::statusETID,0);
 		}
 	}
 
@@ -97,7 +98,7 @@
 	//! resets the motion command and starts it playing
 	void updateMS(const std::string& file) {
 		if(msid==MotionManager::invalid_MC_ID) {
-			msid=motman->addMotion(SharedObject<MotionSequenceMC<SIZE> >(file.c_str()));
+			msid=motman->addPrunableMotion(SharedObject<MotionSequenceMC<SIZE> >(file.c_str()));
 			msidIsMine=true;
 		} else {
 			MMAccessor<MotionSequenceMC<SIZE> > ms(msid);
@@ -120,9 +121,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.6 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:57 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Nodes/SoundNode.h
===================================================================
RCS file: Behaviors/Nodes/SoundNode.h
diff -N Behaviors/Nodes/SoundNode.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Nodes/SoundNode.h	8 Oct 2004 00:08:47 -0000	1.5
@@ -0,0 +1,63 @@
+//-*-c++-*-
+#ifndef INCLUDED_SoundNode_h_
+#define INCLUDED_SoundNode_h_
+
+#include "Behaviors/StateNode.h"
+#include "Events/EventRouter.h"
+#include "SoundPlay/SoundManager.h"
+
+//! A simple StateNode that plays a sound upon startup and throws a status event on completion
+class SoundNode : public StateNode {
+protected:
+  std::string filename;
+  SoundManager::Play_ID curplay_id;
+
+public:
+  //! constructor
+  SoundNode(std::string nodename="SoundNode", std::string soundfilename="") : 
+    StateNode(nodename), filename(soundfilename), curplay_id(SoundManager::invalid_Play_ID) {}
+
+  //! activate the node
+  virtual void DoStart() {
+    curplay_id = sndman->PlayFile(filename);
+    erouter->addListener(this,EventBase::audioEGID,curplay_id,EventBase::deactivateETID);
+    StateNode::DoStart();  // don't activate transitions until our listener has been added
+  }
+
+  //! deactivate the node
+  virtual void DoStop() {
+    erouter->removeListener(this);
+    StateNode::DoStop();
+  }
+
+  //! receive audioEGID status event and throw stateMachineEGID status event
+  virtual void processEvent(const EventBase&) {
+    erouter->postEvent(EventBase::stateMachineEGID,(unsigned int)this,EventBase::statusETID,0);
+  }
+
+  //! interrupts playing of the current sound
+  void StopPlay() {
+    sndman->StopPlay(curplay_id);
+    curplay_id = SoundManager::invalid_Play_ID;
+  }
+
+  //! returns the name of the sound file associated with this node
+  std::string getFileName() { return filename; }
+
+  //! sets the name of the sound file associated with this node
+  void setFileName(std::string &soundfilename) { filename = soundfilename; }
+
+};
+
+/*! @file
+ * @brief Defines SoundNode, a simple StateNode that plays a sound and throws a status event upon completion
+ * @author dst (Creator)
+ *
+ * $Author: dst $
+ * $Name:  $
+ * $Revision: 1.5 $
+ * $State: Exp $
+ * $Date: 2004/10/08 00:08:47 $
+ */
+
+#endif
Index: Behaviors/Nodes/WalkNode.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Nodes/WalkNode.h,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- Behaviors/Nodes/WalkNode.h	29 Oct 2003 22:36:20 -0000	1.3
+++ Behaviors/Nodes/WalkNode.h	17 Oct 2004 01:16:10 -0000	1.5
@@ -90,7 +90,7 @@
 		if(walkid==MotionManager::invalid_MC_ID) {
 			SharedObject<WalkMC> walk;
 			walk->setTargetVelocity(xvel,yvel,avel);
-			walkid=motman->addMotion(walk);
+			walkid=motman->addPersistentMotion(walk);
 			walkidIsMine=true;
 		} else {
 			MMAccessor<WalkMC> walk(walkid);
@@ -111,9 +111,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2003/10/29 22:36:20 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
 #endif
Index: Behaviors/Transitions/CompareTrans.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transitions/CompareTrans.h,v
retrieving revision 1.5
retrieving revision 1.7
diff -u -d -r1.5 -r1.7
--- Behaviors/Transitions/CompareTrans.h	11 Nov 2003 00:08:18 -0000	1.5
+++ Behaviors/Transitions/CompareTrans.h	7 Oct 2004 19:07:05 -0000	1.7
@@ -43,28 +43,28 @@
 	virtual void DoStart() { Transition::DoStart(); erouter->addListener(this,poller); }
 
 	//!stops listening
-	virtual void DoStop() { erouter->forgetListener(this); Transition::DoStop(); }
+	virtual void DoStop() { erouter->removeListener(this); Transition::DoStop(); }
 
 	//!don't care about the event, just a pulse to check the values
 	virtual void processEvent(const EventBase&) {
 		switch(tst) {
 		case LT:
-			if(*mon<val) activate();
+			if(*mon<val) fire();
 			break;
 		case GT:
-			if(val<*mon) activate();
+			if(val<*mon) fire();
 			break;
 		case LTE:
-			if(!(val<*mon)) activate();
+			if(!(val<*mon)) fire();
 			break;
 		case GTE:
-			if(!(*mon<val)) activate();
+			if(!(*mon<val)) fire();
 			break;
 		case EQ:
-			if(*mon==val) activate();
+			if(*mon==val) fire();
 			break;
 		case NE:
-			if(!(*mon==val)) activate();
+			if(!(*mon==val)) fire();
 			break;
 		}
 	}
@@ -88,9 +88,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2003/11/11 00:08:18 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
 #endif
Index: Behaviors/Transitions/CompletionTrans.h
===================================================================
RCS file: Behaviors/Transitions/CompletionTrans.h
diff -N Behaviors/Transitions/CompletionTrans.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Transitions/CompletionTrans.h	17 Oct 2004 01:16:10 -0000	1.6
@@ -0,0 +1,74 @@
+//-*-c++-*-
+#ifndef INCLUDED_CompletionTrans_h_
+#define INCLUDED_CompletionTrans_h_
+
+#include "Behaviors/StateNode.h"
+#include "Behaviors/Transition.h"
+#include "Events/EventRouter.h"
+
+//! causes a transition when at least @e n sources have signalled completion;  @e n = 0 means "all" (default)
+class CompletionTrans : public Transition {
+protected:
+  int minsrcs;
+  bool *completions;  //!< pointer to array for recording completion events for all sources
+
+public:
+  CompletionTrans(StateNode* destination, int n=0) :
+    Transition(destination), minsrcs(n), completions(NULL) {};
+
+  //! starts listening
+  virtual void DoStart() {
+    Transition::DoStart();
+    unsigned int const numsrcs = getSources().size();
+    completions = new bool[numsrcs];
+    for (unsigned int i = 0; i < numsrcs; i++) {
+      completions[i] = false;
+      erouter->addListener(this,
+			   EventBase::stateMachineEGID,
+			   (unsigned int)getSources()[i],
+			   EventBase::statusETID);
+    };
+  }
+
+  //! stops listening
+  virtual void DoStop() {
+    erouter->removeListener(this);
+    delete completions;
+    completions = NULL;
+    Transition::DoStop();
+  }
+
+  //! record completions, and fire the transition if all sources have completed
+  virtual void processEvent(const EventBase &event) {
+    int numcomplete = 0;
+    for ( unsigned int i=0; i<getSources().size(); i++ ) {
+      if ( event.getSourceID() == (unsigned int)getSources()[i] )
+	completions[i] = true;
+      if ( completions[i] ) ++numcomplete;
+    };
+    int const threshold = (minsrcs > 0 ? minsrcs : (int)getSources().size());
+    if (numcomplete >= threshold) fire();
+  }
+
+  virtual std::string getName() const { return "CompletionTrans"; }
+
+protected:
+  //!@name Dummy functions to satisfy the compiler
+  CompletionTrans(const CompletionTrans&);  //!< don't call this
+  CompletionTrans& operator=(const CompletionTrans&);  //!< don't call this
+  //@}
+
+};
+
+/*! @file
+ * @brief Defines Completiontrans, which causes a transition if all sources have signalled completion
+ * @author dst (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.6 $
+ * $State: Exp $
+ * $Date: 2004/10/17 01:16:10 $
+ */
+
+#endif
Index: Behaviors/Transitions/EventTrans.h
===================================================================
RCS file: Behaviors/Transitions/EventTrans.h
diff -N Behaviors/Transitions/EventTrans.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Transitions/EventTrans.h	7 Oct 2004 19:07:05 -0000	1.3
@@ -0,0 +1,62 @@
+//-*-c++-*-
+#ifndef INCLUDED_EventTrans_h_
+#define INCLUDED_EventTrans_h_
+
+#include "Behaviors/Transition.h"
+#include "Events/EventRouter.h"
+
+//! causes a transition when the specified event is received
+
+class EventTrans : public Transition {
+private:
+  int argcount;
+  EventBase::EventGeneratorID_t egid;
+  unsigned int esid;
+  EventBase::EventTypeID_t etid;
+
+public:
+  EventTrans(StateNode* destination, EventBase::EventGeneratorID_t gid) :
+    Transition(destination), argcount(1), egid(gid), esid(0), etid(EventBase::statusETID) {};
+
+  EventTrans(StateNode* destination, EventBase::EventGeneratorID_t gid, unsigned int sid) :
+    Transition(destination), argcount(2), egid(gid), esid(sid), etid(EventBase::statusETID) {};
+
+  EventTrans(StateNode* destination, EventBase::EventGeneratorID_t gid, 
+	     unsigned int sid, EventBase::EventTypeID_t tid) :
+    Transition(destination), argcount(3), egid(gid), esid(sid), etid(tid) {};
+
+  //! starts listening
+  virtual void DoStart() {
+    Transition::DoStart();
+    switch (argcount) {
+    case 1: erouter->addListener(this,egid); break;
+    case 2: erouter->addListener(this,egid,esid); break;
+    case 3: erouter->addListener(this,egid,esid,etid);
+    };
+  }
+
+  //! stops listening
+  virtual void DoStop() {
+    erouter->removeListener(this);
+    Transition::DoStop();
+  }
+
+  //! fire the transition if an event is seen
+  virtual void processEvent(const EventBase&) { fire(); }
+
+  virtual std::string getName() const { return "EventTrans"; }
+
+};
+
+/*! @file
+ * @brief Defines EventTrans, which causes a transition if an event of the specified type occurs
+ * @author dst (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.3 $
+ * $State: Exp $
+ * $Date: 2004/10/07 19:07:05 $
+ */
+
+#endif
Index: Behaviors/Transitions/NullTrans.h
===================================================================
RCS file: Behaviors/Transitions/NullTrans.h
diff -N Behaviors/Transitions/NullTrans.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Behaviors/Transitions/NullTrans.h	7 Oct 2004 19:07:05 -0000	1.3
@@ -0,0 +1,41 @@
+//-*-c++-*-
+#ifndef INCLUDED_NullTrans_h_
+#define INCLUDED_NullTrans_h_
+
+#include "Behaviors/Transition.h"
+#include "Events/EventRouter.h"
+
+//! a transition that occurs (via a 0 msec Timer event) as soon as the source node finishes starting up
+class NullTrans : public Transition {
+public:
+  //! constructor
+  NullTrans(StateNode* destination) : Transition(destination) {}
+	
+  //!starts 0 msec timer, so transition will occur very soon
+  virtual void DoStart() {
+    Transition::DoStart();
+    erouter->addTimer(this,0,0,false);
+  }
+
+  //!stops timer
+  virtual void DoStop() { erouter->removeListener(this); Transition::DoStop(); }
+
+  //!when timer event is received, fire() the transition
+  virtual void processEvent(const EventBase&) { fire(); }
+
+  virtual std::string getName() const { return "TimeOutTrans"; }
+
+};
+
+/*! @file
+ * @brief Defines NullTrans, which causes a transition as soon as the source node finishes starting up
+ * @author dst (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.3 $
+ * $State: Exp $
+ * $Date: 2004/10/07 19:07:05 $
+ */
+
+#endif
Index: Behaviors/Transitions/TimeOutTrans.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transitions/TimeOutTrans.h,v
retrieving revision 1.9
retrieving revision 1.12
diff -u -d -r1.9 -r1.12
--- Behaviors/Transitions/TimeOutTrans.h	11 Nov 2003 00:08:18 -0000	1.9
+++ Behaviors/Transitions/TimeOutTrans.h	7 Oct 2004 19:07:05 -0000	1.12
@@ -8,35 +8,35 @@
 //! causes a transition after a specified amount of time has passed
 class TimeOutTrans : public Transition {
 public:
-	//! constructor, specify delay in milliseconds
-	TimeOutTrans(StateNode* destination, unsigned int delay) : Transition(destination), d(delay) {}
-	
-	//!starts timer
-	virtual void DoStart() {
-		Transition::DoStart();
-		resetTimer(); 
-	}
+  //! constructor, specify delay in milliseconds
+  TimeOutTrans(StateNode* destination, unsigned int delay) : Transition(destination), d(delay) {}
 
-	//!stops timer
-	virtual void DoStop() { erouter->forgetListener(this); Transition::DoStop(); }
+  //!starts timer
+  virtual void DoStart() {
+    Transition::DoStart();
+    resetTimer(); 
+  }
 
-	//!resets timer
-	void resetTimer() {
-		//std::cout << "Reset @ " << get_time() << " stop @ " << get_time()+d << ' ' << this << std::endl;
-		erouter->addTimer(this,0,d,false);
-	}
+  //!stops timer
+  virtual void DoStop() { erouter->removeListener(this); Transition::DoStop(); }
+  
+  //!resets timer
+  void resetTimer() {
+    // std::cout << "Reset @ " << get_time() << " stop @ " << get_time()+d << ' ' << this << std::endl;
+    erouter->addTimer(this,0,d,false);
+  }
 
-	//!if we receive the timer event, activate()
-	virtual void processEvent(const EventBase& e) {
-		std::cout << "Timeout @ " << get_time() << " from " << e.getName() << ' ' << this << std::endl;
-		activate();
-	}
+  //!if we receive the timer event, fire()
+  virtual void processEvent(const EventBase&) {
+    // std::cout << "Timeout @ " << get_time() << " from " << event.getName() << ' ' << this << std::endl;
+    fire();
+  }
 
-	virtual std::string getName() const { return "TimeOutTrans"; }
+  virtual std::string getName() const { return "TimeOutTrans"; }
 
 protected:
-	//!amount to delay (in milliseconds) before transition
-	unsigned int d;
+  //!amount to delay (in milliseconds) before transition
+  unsigned int d;
 };
 
 /*! @file
@@ -45,9 +45,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.12 $
  * $State: Exp $
- * $Date: 2003/11/11 00:08:18 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
 #endif
Index: Behaviors/Transitions/VisualTargetCloseTrans.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transitions/VisualTargetCloseTrans.h,v
retrieving revision 1.9
retrieving revision 1.12
diff -u -d -r1.9 -r1.12
--- Behaviors/Transitions/VisualTargetCloseTrans.h	23 Dec 2003 06:33:42 -0000	1.9
+++ Behaviors/Transitions/VisualTargetCloseTrans.h	7 Oct 2004 19:07:05 -0000	1.12
@@ -20,9 +20,9 @@
 	virtual void DoStart() { Transition::DoStart(); erouter->addListener(this,EventBase::visObjEGID,sid); }
 
 	//!called by StateNode when it becomes inactive - undo whatever you did in Enable()
-	virtual void DoStop() { erouter->forgetListener(this); Transition::DoStop(); }
+	virtual void DoStop() { erouter->removeListener(this); Transition::DoStop(); }
 
-	//!if the object is "close", calls activate()
+	//!if the object is "close", calls fire()
 	virtual void processEvent(const EventBase& e) {
 		const VisionObjectEvent* ve=dynamic_cast<const VisionObjectEvent*>(&e);
 		ASSERTRET(ve!=NULL,"Casting error");
@@ -37,8 +37,8 @@
 			IRDistOffset=ERS220Info::IRDistOffset;
 		else if(state->robotDesign & WorldState::ERS7Mask)
 			IRDistOffset=ERS7Info::NearIRDistOffset;
-		if(x*x+y*y<0.02f && IRDistOffset!=-1U && state->sensors[IRDistOffset]<300)
-			activate();
+		if(x*x+y*y<0.02f && IRDistOffset!=-1U && state->sensors[IRDistOffset]<225)
+			fire();
 	}
 
 	virtual std::string getName() const { return "VisualTargetCloseTrans"; }
@@ -54,9 +54,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.12 $
  * $State: Exp $
- * $Date: 2003/12/23 06:33:42 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
 #endif
Index: Behaviors/Transitions/VisualTargetTrans.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Behaviors/Transitions/VisualTargetTrans.h,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -d -r1.9 -r1.11
--- Behaviors/Transitions/VisualTargetTrans.h	8 Dec 2003 00:21:02 -0000	1.9
+++ Behaviors/Transitions/VisualTargetTrans.h	7 Oct 2004 19:07:05 -0000	1.11
@@ -26,13 +26,13 @@
 	//!called by StateNode when it becomes inactive - undo whatever you did in Enable()
 	virtual void DoStop() {
 		//serr->printf("VisualTargetTrans::DoStop() - enter\n");
-		erouter->forgetListener(this);
+		erouter->removeListener(this);
 		count=0;
 		Transition::DoStop();
 		//serr->printf("VisualTargetTrans::DoStop() - leave\n");
 	}
 
-	//!if the object is "close", calls activate()
+	//!if the object is "close", calls fire()
 	virtual void processEvent(const EventBase& e) {
 		//serr->printf("VisualTargetTrans::processEvent() - enter %d\n",get_time());
 
@@ -41,7 +41,7 @@
 		else
 			count++;
 		if(count>5)
-			activate();
+			fire();
 
 		//serr->printf("VisualTargetTrans::processEvent() - leave %d\n",get_time());
 	}
@@ -61,9 +61,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.11 $
  * $State: Exp $
- * $Date: 2003/12/08 00:21:02 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
 #endif
Index: Events/ButtonEvent.cc
===================================================================
RCS file: Events/ButtonEvent.cc
diff -N Events/ButtonEvent.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Events/ButtonEvent.cc	16 Sep 2004 20:39:53 -0000	1.1
@@ -0,0 +1,86 @@
+#include "ButtonEvent.h"
+#include <sstream>
+
+std::string
+ButtonEvent::getDescription(bool /*showTypeSpecific=true*/, unsigned int verbosity/*=0*/) const {
+	std::ostringstream logdata;
+	logdata << getName();
+	char hexstring[30];
+	snprintf(hexstring,sizeof(hexstring),"0x%x",getSourceID());
+	logdata << '\t' << hexstring;
+	switch(getTypeID()) {
+	case EventBase::activateETID:
+		logdata << "\tA"; break;
+	case EventBase::statusETID:
+		logdata << "\tS"; break;
+	case EventBase::deactivateETID:
+		logdata << "\tD"; break;
+	case EventBase::numETIDs:
+		logdata << "\tU"; break;  //UNKNOWN TYPE
+	}
+	if(verbosity>=1)
+		logdata << '\t' << getDuration() << '\t' << getTimeStamp();
+	if(verbosity>=2)
+		logdata << '\t' << getMagnitude();
+	return logdata.str();
+}
+
+unsigned int
+ButtonEvent::getBinSize() const {
+	unsigned int used=0;
+	used+=creatorSize("ButtonEvent");
+	used+=EventBase::getBinSize();
+	return used;
+}
+
+unsigned int
+ButtonEvent::LoadBuffer(const char buf[], unsigned int len) {
+	unsigned int origlen=len;
+	unsigned int used=0;
+	if(0==(used=checkCreator("ButtonEvent",buf,len,true))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=EventBase::LoadBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	return origlen-len;	
+}
+
+unsigned int
+ButtonEvent::SaveBuffer(char buf[], unsigned int len) const {
+	unsigned int origlen=len;
+	unsigned int used=0;
+	if(0==(used=saveCreator("ButtonEvent",buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=EventBase::SaveBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	return origlen-len;
+}
+
+void
+ButtonEvent::genName() {
+	if(!nameisgen)
+		return;
+	if(genID<numEGIDs) {
+		stim_id=std::string("Evt_");
+		stim_id+=EventGeneratorNames[genID];
+	} else {
+		stim_id=std::string("Evt_InvalidGen");
+		stim_id+=genID; 
+	}
+	stim_id+="::";
+	char tmp[16];
+	snprintf(tmp,16,"0x%x",sourceID);
+	stim_id+=tmp;
+}
+
+
+/*! @file
+ * @brief 
+ * @author YOURNAMEHERE (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/09/16 20:39:53 $
+ */
+
Index: Events/ButtonEvent.h
===================================================================
RCS file: Events/ButtonEvent.h
diff -N Events/ButtonEvent.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Events/ButtonEvent.h	16 Sep 2004 20:39:53 -0000	1.1
@@ -0,0 +1,41 @@
+//-*-c++-*-
+#ifndef INCLUDED_ButtonEvent_h_
+#define INCLUDED_ButtonEvent_h_
+
+#include "EventBase.h"
+
+//! redefines getName and getDescription to use the button names instead of numerical source IDs (doesn't define any new data members - magnitude is used for pressure sensitive buttons)
+class ButtonEvent : public EventBase {
+public:
+	/*! @name Constructors/Destructors */
+	//! constructor
+	/*! @see EventRouter::postEvent() */
+	ButtonEvent() : EventBase() {}
+	ButtonEvent(unsigned int sid, EventTypeID_t tid, unsigned int dur, float mag) : EventBase(buttonEGID,sid,tid) { setDuration(dur); setMagnitude(mag); }
+	virtual ~ButtonEvent() {} //!< destructor
+	//@}
+	
+	virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const; 
+
+	//! Useful for serializing events to send between processes
+	/*! @name LoadSave interface */
+	virtual unsigned int getBinSize() const;
+	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
+	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
+	//@}
+protected:
+	virtual void genName();
+};
+
+/*! @file
+ * @brief Describes ButtonEvent, redefines getName and getDescription to use the button names instead of numerical source IDs
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/09/16 20:39:53 $
+ */
+
+#endif
Index: Events/EventBase.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventBase.cc,v
retrieving revision 1.15
retrieving revision 1.19
diff -u -d -r1.15 -r1.19
--- Events/EventBase.cc	5 Dec 2003 20:26:42 -0000	1.15
+++ Events/EventBase.cc	28 Sep 2004 23:07:02 -0000	1.19
@@ -1,30 +1,34 @@
 #include "EventBase.h"
 #include <stdio.h>
+#include <sstream>
 
 const char* const EventBase::EventGeneratorNames[numEGIDs] = {
-	"UnknownGen",
-	"AI",
-	"Audio",
-	"Button",
-	"EventRouter",
-	"EStop",
-	"Locomotion",
-	"MotionManager",
-	"Power",
-	"Sensor",
-	"StateMachine",
-	"TextMsg",
-	"Timer",
-	"VisionOFbkVector",
-	"VisionRawCamera",
-	"VisionInterleaver",
-	"VisionJPEGCompressor",
-	"VisionSegmenter",
-	"VisionRLEEncoder",
-	"VisionRegionConnector",
-	"VisionObjectDetector",
-	"WMVariable",
-	"WorldModel",
+	"unknownEGID",
+	"aiEGID",
+	"audioEGID",
+	"buttonEGID",
+	"erouterEGID",
+	"estopEGID",
+	"locomotionEGID",
+	"micOSndEGID",
+	"micRawEGID",
+	"micFFTEGID",
+	"motmanEGID",
+	"powerEGID",
+	"sensorEGID",
+	"stateMachineEGID",
+	"testmsgEGID",
+	"timerEGID",
+	"visOFbkEGID",
+	"visRawCameraEGID",
+	"visInterleaveEGID",
+	"visJPEGEGID",
+	"visSegmentEGID",
+	"visRLEEGID",
+	"visRegionEGID",
+	"visObjEGID",
+	"wmVarEGID",
+	"worldModelEGID",
 };
 
 
@@ -50,6 +54,29 @@
 	
 }
 
+std::string
+EventBase::getDescription(bool /*showTypeSpecific=true*/, unsigned int verbosity/*=0*/) const {
+	std::ostringstream logdata;
+	logdata << getName();
+	char hexstring[30];
+	snprintf(hexstring,sizeof(hexstring),"0x%x",getSourceID());
+	logdata << '\t' << hexstring;
+	switch(getTypeID()) {
+	case EventBase::activateETID:
+		logdata << "\tA"; break;
+	case EventBase::statusETID:
+		logdata << "\tS"; break;
+	case EventBase::deactivateETID:
+		logdata << "\tD"; break;
+	case EventBase::numETIDs:
+		logdata << "\tU"; break;  //UNKNOWN TYPE
+	}
+	if(verbosity>=1)
+		logdata << '\t' << getDuration() << '\t' << getTimeStamp();
+	if(verbosity>=2)
+		logdata << '\t' << getMagnitude();
+	return logdata.str();
+}
 
 unsigned int
 EventBase::getBinSize() const {
@@ -142,8 +169,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.15 $
+ * $Revision: 1.19 $
  * $State: Exp $
- * $Date: 2003/12/05 20:26:42 $
+ * $Date: 2004/09/28 23:07:02 $
  */
 
Index: Events/EventBase.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventBase.h,v
retrieving revision 1.21
retrieving revision 1.27
diff -u -d -r1.21 -r1.27
--- Events/EventBase.h	9 Feb 2004 22:45:28 -0000	1.21
+++ Events/EventBase.h	18 Oct 2004 16:59:20 -0000	1.27
@@ -12,6 +12,10 @@
  *  you have to do is add a new entry to the ID list (#EventGeneratorID_t)
  *  and then put its name in the #EventGeneratorNames[] array.
  *
+ *  The #EventGeneratorID_t list should contain links to the
+ *  generators' documentation, or will directly give information about
+ *  what to expect in events from that generator.
+ *  
  *  Alternatively, there is an 'unlicensed spectrum' available under
  *  the #unknownEGID.  You can send out events from that generator just
  *  like any other, but it should only be used for quick tests and hacking
@@ -23,14 +27,19 @@
  *  #visObjEGID) refers to seeing a particular object.  These SIDs are
  *  usually defined in the generators themselves.
  *
+ *  If more information needs to be sent along with the event, the
+ *  cleanest solution is to create a subclass of EventBase to hold the
+ *  additional information.  For example, you can see the existing
+ *  subclasses in the inheritance diagram above.  If you want to use a
+ *  quick hack however, you could assume the pointer size is the same
+ *  as an unsigned int and just pass a pointer to data as the SID.
+ *  Your funeral, err, I mean your call. ;)
+ *
  *  The #duration field is also generator specific - some may refer to
  *  the time since the last activation event (e.g. button events)
  *  where as others refer to time since last status (e.g. sensors
  *  updates)
  *
- *  The #EventGeneratorID_t list should contain links to the
- *  generators' documentation, or will directly give information about
- *  what to expect in events from that generator.
  */
 class EventBase : public LoadSave {
  public:
@@ -43,16 +52,19 @@
 		aiEGID,           //!< not being used, yet (might use this when AI makes decisions?)
 		audioEGID,        //!< Sends an event when a sound starts/ends playback, status events as chained sounds end; SID is SoundManager::Play_ID; duration is playtime
 		buttonEGID,       //!< Sends activate event for button down, deactivate for button up.  Status events only for when pressure sensitive buttons' reading changes. (on sensorEGID updates); SIDs are from ButtonOffset_t in the namespace of the target model (e.g. ERS210Info::ButtonOffset_t); duration is button down time
-		erouterEGID,      //!< Sends activate event on first listener, deactivate on last listener, and status on other listener changes.; SID is the generator ID affected (NOT IMPLEMENTED YET)
+		erouterEGID,      //!< Sends activate event on first listener, deactivate on last listener, and status on other listener changes.; SID is the generator ID affected
 		estopEGID,        //!< Sends an event when the estop is turned on or off; SID is the MotionManager::MC_ID of the EmergencyStopMC; duration is length of estop activation
 		locomotionEGID,   //!< Sends events regarding transportation in the world; you can/should assume these will all be LocomotionEvent classes; SID is MotionManager::MC_ID of posting MotionCommand; duration is the time since last velocity change of that MC. (You could generate these for things other than walking...)
-		motmanEGID,       //!< Sends events when a MotionCommand is added or removed, SID is is the MotionManager::MC_ID, duration is always 0
+		micOSndEGID,      //!< Sends a DataEvent<OSoundVectorData> for every audio buffer received from the system; SID and duration are always 0 (This is generated by the MainObj instantiation of MMCombo)
+		micRawEGID,       //!< reserved for future use
+		micFFTEGID,       //!< reserved for future use
+		motmanEGID,       //!< Sends events when a MotionCommand is added or removed, SID is is the MotionManager::MC_ID, duration is always 0; individual MotionCommands may throw status events to signal intermediary status
 		powerEGID,        //!< Sends events for low power warnings, temperature, etc. see PowerSourceID::PowerSourceID_t
 		sensorEGID,       //!< Sends a status event when new sensor readings are available. see SensorSourceID::SensorSourceID_t
 		stateMachineEGID, //!< Sends an event upon entering and leaving a StateNode; SID is pointer to the StateNode; duration is always 0
     textmsgEGID,      //!< Sends status events when a text msg is received on console; generated by the Controller, SID is always -1; durations is always 0 (see Controller for more information)
 		timerEGID,        //!< Sends timer events; you set timers explicitly, you don't have to listen as well. (See EventRouter::addTimer()) There's no cross-talk, only the listener which requested the timer will receive it; SID is whatever you requested it to be; duration is the time (since boot, in ms) that the timer was supposed to go off; these are always status
-		visOFbkEGID,      //!< Sends a DataEvent <OFbkImageVectorData> for every camera image received from the system; SID and duration are always 0 (This is generated by the MainObj instantiation of MMCombo)
+		visOFbkEGID,      //!< Sends a DataEvent < OFbkImageVectorData > for every camera image received from the system; SID and duration are always 0 (This is generated by the MainObj instantiation of MMCombo)
 		visRawCameraEGID, //!< Sends a FilterBankEvent when new raw camera images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
 		visInterleaveEGID,//!< Sends a FilterBankEvent when new interleaved images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
 		visJPEGEGID,      //!< Sends a FilterBankEvent when JPEG compressed images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
@@ -109,6 +121,15 @@
 	virtual const std::string& resetName() { nameisgen=true; genName(); return stim_id; } //!< resets name to generated form, overwriting any previous name
 	virtual bool isCustomName() const { return !nameisgen; } //!< returns true if not using the generated name
 
+	//! generates a description of the event with variable verbosity 
+	/*! @param showTypeSpecific will signal subclasses to add additional information
+	 *  @param verbosity can be one of the following values:
+	 *    - 0 - the name and type
+	 *    - 1 - the name, type, duration, and timestamp
+	 *    - 2 and above - the name, type, duration, and magnitude
+	 *  if showTypeSpecific, additional fields will be added after the common fields listed above. */
+	virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const; 
+
 	inline bool operator<(const EventBase& e) const { return timestamp<e.timestamp; }
 
 	//! is true if the genID, typeID, and sourceID's all match
@@ -156,9 +177,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.21 $
+ * $Revision: 1.27 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/10/18 16:59:20 $
  */
 
 #endif
Index: Events/EventGeneratorBase.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventGeneratorBase.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Events/EventGeneratorBase.cc	8 Dec 2003 00:21:05 -0000	1.1
+++ Events/EventGeneratorBase.cc	7 Oct 2004 19:07:05 -0000	1.2
@@ -10,7 +10,7 @@
 
 void
 EventGeneratorBase::DoStop() {
-	erouter->forgetListener(this);
+	erouter->removeListener(this);
 	BehaviorBase::DoStop();
 }
 
@@ -20,8 +20,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * $State: Exp $
- * $Date: 2003/12/08 00:21:05 $
+ * $Date: 2004/10/07 19:07:05 $
  */
 
Index: Events/EventRouter.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventRouter.cc,v
retrieving revision 1.10
retrieving revision 1.13
diff -u -d -r1.10 -r1.13
--- Events/EventRouter.cc	3 Oct 2003 03:41:01 -0000	1.10
+++ Events/EventRouter.cc	7 Oct 2004 22:14:17 -0000	1.13
@@ -38,9 +38,14 @@
 	//		cout << "done" << endl;
 }
 
-/*! timers are unique by EventListener and source ID - can't have two timers for the same el and sid
- *  a delay of 0 with repeating will cause an event to be sent at every opportunity, use very sparingly
- *  a delay of -1U will call removeTimer() if it already exists, otherwise is ignored
+/*! timers are unique by EventListener and source ID - can't have two timers for the same el and sid\n
+ *  a delay of 0 with repeating will cause an event to be sent at every opportunity, use sparingly\n
+ *  a delay of -1U will call removeTimer() if it already exists, otherwise is ignored\n
+ *
+ *  To add a timer, you can also call addListener() with EventBase::timerEGID and the sid
+ *  and delay (in the EventBase::duration field) - this method will simply cause this
+ *  function to be called internally.
+ *
  *  @param el the EventListener to send the timer event to
  *  @param sid the source ID to use on that event (if you need to send more info, send a pointer to a struct of your devising, typecasted as int)
  *  @param delay the delay between the first (and future) calls
@@ -66,54 +71,220 @@
 	//	chkTimers();
 }
 
-void EventRouter::addListener(EventListener* el, const EventBase& e) {
-	if(e.getGeneratorID()==EventBase::timerEGID)
-		addTimer(el,e.getSourceID(),e.getDuration());
-	else
-		listeners.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
+void EventRouter::removeTimer(EventListener* el) {
+	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
+		if((*it)->el==el) {
+			delete *it;
+			*it=NULL;
+		}
+	timers.erase(remove(timers.begin(),timers.end(),(const TimerEntry*)NULL),timers.end());
+}
+
+void EventRouter::removeTimer(EventListener* el, unsigned int sid) {
+	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
+		if((*it)->el==el && (*it)->sid==sid) {
+			delete *it;
+			timers.erase(it);
+			return;
+		}
+}
+
+void EventRouter::removeAllTimers() {
+	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
+		delete *it;
+	timers.erase(timers.begin(),timers.end());
 }
+
 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid) {
+	bool hadListener=hasListeners(egid);
 	listeners.addMapping(el,egid); 
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
 }
 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
+	bool hadListener=hasListeners(egid);
 	for(unsigned int et=0; et<EventBase::numETIDs; et++)
 		listeners.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
 }
 void EventRouter::addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+	bool hadListener=hasListeners(egid);
 	listeners.addMapping(el,egid,sid,etid);
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+void EventRouter::addListener(EventListener* el, const EventBase& e) {
+	if(e.getGeneratorID()==EventBase::timerEGID)
+		addTimer(el,e.getSourceID(),e.getDuration());
+	else {
+		bool hadListener=hasListeners(e.getGeneratorID());
+		listeners.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
+		if(!hadListener)
+			postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID));
+		else
+			postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID));
+	}
 }
 
+void EventRouter::removeListener(EventListener* el) {
+	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
+		removeListener(el,(EventBase::EventGeneratorID_t)eg);
+}
+void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid) {
+	if(egid==EventBase::timerEGID)
+		removeTimer(el);
+	else {
+		if(!listeners.removeMapping(el,egid))
+			return; //nothing was removed, don't want to clean up or throw an event
+		listeners.clean(egid);
+		if(!hasListeners(egid))
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+		else
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+	}
+}
+void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
+	if(egid==EventBase::timerEGID)
+		removeTimer(el,sid);
+	else {
+		unsigned int removed=0;
+		for(unsigned int et=0; et<EventBase::numETIDs; et++)
+			removed+=listeners.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
+		if(!removed)
+			return; //nothing was removed, don't want to clean up or throw an event
+		listeners.clean(egid);
+		if(!hasListeners(egid))
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+		else
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+	}
+}
+void EventRouter::removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+	if(egid==EventBase::timerEGID) {
+		if(etid==EventBase::statusETID)
+			removeTimer(el,sid);
+	} else {
+		if(!listeners.removeMapping(el,egid,sid,etid))
+			return; //nothing was removed, don't want to clean up or throw an event
+		listeners.clean(egid);
+		if(!hasListeners(egid))
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+		else
+			postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+	}
+}
 void EventRouter::removeListener(EventListener* el, const EventBase& e) {
 	if(e.getGeneratorID()==EventBase::timerEGID)
 		removeTimer(el,e.getSourceID());
 	else {
-		listeners.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
-		listeners.clean();
+		if(!listeners.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
+			return; //nothing was removed, don't want to clean up or throw an event
+		listeners.clean(e.getGeneratorID());
+		if(!hasListeners(e.getGeneratorID()))
+			postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID));
+		else
+			postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID));
 	}
 }
 
-void EventRouter::removeTimer(EventListener* el) {
-	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
-		if((*it)->el==el) {
-			delete *it;
-			*it=NULL;
-		}
-	timers.erase(remove(timers.begin(),timers.end(),(const TimerEntry*)NULL),timers.end());
+void EventRouter::forgetListener(EventListener* el) {
+	removeListener(el);
 }
 
-void EventRouter::removeTimer(EventListener* el, unsigned int sid) {
-	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
-		if((*it)->el==el && (*it)->sid==sid) {
-			delete *it;
-			timers.erase(it);
-			return;
-		}
+void EventRouter::addTrapper(EventTrapper* el, const EventBase& e) {
+	bool hadListener=hasListeners(e.getGeneratorID());
+	trappers.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID());
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID));
+}
+/*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
+void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) {
+	bool hadListener=hasListeners(egid);
+	trappers.addMapping(el,egid);
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+/*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
+void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
+	bool hadListener=hasListeners(egid);
+	for(unsigned int et=0; et<EventBase::numETIDs; et++)
+		trappers.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+/*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
+void EventRouter::addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+	bool hadListener=hasListeners(egid);
+	trappers.addMapping(el,egid,sid,etid);
+	if(!hadListener)
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::activateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
 }
 
-void EventRouter::removeAllTimers() {
-	for(timer_it_t it=timers.begin(); it!=timers.end(); it++)
-		delete *it;
-	timers.erase(timers.begin(),timers.end());
+/*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
+void EventRouter::addTrapper(EventTrapper* el) {
+	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
+		addTrapper(el,(EventBase::EventGeneratorID_t)eg);
+}
+
+
+void EventRouter::removeTrapper(EventTrapper* el, const EventBase& e) {
+	if(!trappers.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()))
+		return; //nothing was removed, don't want to clean up or throw an event
+	trappers.clean(e.getGeneratorID());
+	if(!hasListeners(e.getGeneratorID()))
+		postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::deactivateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,e.getGeneratorID(),EventBase::statusETID));
+}
+void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) {
+	if(!trappers.removeMapping(el,egid))
+		return; //nothing was removed, don't want to clean up or throw an event
+	trappers.clean(egid);
+	if(!hasListeners(egid))
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) {
+	int removed=0;
+	for(unsigned int et=0; et<EventBase::numETIDs; et++)
+		removed+=trappers.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et);
+	if(!removed)
+		return; //nothing was removed, don't want to clean up or throw an event
+	trappers.clean(egid);
+	if(!hasListeners(egid))
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+void EventRouter::removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+	if(!trappers.removeMapping(el,egid,sid,etid))
+		return; //nothing was removed, don't want to clean up or throw an event
+	trappers.clean(egid);
+	if(!hasListeners(egid))
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::deactivateETID));
+	else
+		postEvent(new EventBase(EventBase::erouterEGID,egid,EventBase::statusETID));
+}
+
+void EventRouter::removeTrapper(EventTrapper* el) {
+	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
+		removeTrapper(el,(EventBase::EventGeneratorID_t)eg);
 }
 
 void EventRouter::processEventBuffer() { //clears buffered events
@@ -183,9 +354,11 @@
 	elv->push_back(el); // now that everything's set up, we can add the listener
 }
 
-void EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid) {
+bool EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid) {
 	// remove listener from allevents
+	unsigned int numlist=allevents[egid].size();
 	allevents[egid].erase(remove(allevents[egid].begin(),allevents[egid].end(),el),allevents[egid].end());
+	bool hadListener=allevents[egid].size()!=numlist;
 	
 	// now remove listener from all of the filtered events
 	for(unsigned int et=0; et<EventBase::numETIDs; et++) {
@@ -194,53 +367,64 @@
 			SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
 			for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) {// go through each sourceID, delete EL
 				std::vector<void*> * v=&(*mapit).second;
-				v->erase(remove(v->begin(),v->end(),el),v->end());
+				std::vector<void*>::iterator last=remove(v->begin(),v->end(),el);
+				if(last!=v->end()) {
+					hadListener=true;
+					v->erase(last,v->end());
+				}
 			}
 		}
 	}
+	return hadListener;
 }
 
-void EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+bool EventRouter::EventMapper::removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) {
+	bool hadListener=false;
 	SIDtoListenerVectorMap_t* mapping=filteredevents[egid][etid];
 	if(mapping!=NULL) { // if there are subscribers to this egid/etid
 		SIDtoListenerVectorMap_t::iterator mapit=mapping->find(sid);
 		if(mapit!=mapping->end()) {
 			std::vector<void*> * v=&(*mapit).second;
-			v->erase(remove(v->begin(),v->end(),el),v->end());
+			std::vector<void*>::iterator last=remove(v->begin(),v->end(),el);
+			if(last!=v->end()) {
+				hadListener=true;
+				v->erase(last,v->end());
+			}
 		}
 	}
+	return hadListener;
 }
 
 void EventRouter::EventMapper::clean() {
+	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++)
+		clean((EventBase::EventGeneratorID_t)eg);
+}
+void EventRouter::EventMapper::clean(EventBase::EventGeneratorID_t egid) {
 	// first, remove any empty sid vectors from all the mappings
-	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
-		for(unsigned int et=0; et<EventBase::numETIDs; et++) {
-			SIDtoListenerVectorMap_t* mapping=filteredevents[eg][et];
-			if(mapping!=NULL) { // if there are subscribers to this egid/etid
-				SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
-				bool done=false;
-				while(!done) {
-					done=true;
-					for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) { // go through each sourceID vector
-						if((*mapit).second.size()==0) {
-							mapping->erase(mapit);
-							done=false;
-							break;
-						}
+	for(unsigned int et=0; et<EventBase::numETIDs; et++) {
+		SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
+		if(mapping!=NULL) { // if there are subscribers to this egid/etid
+			SIDtoListenerVectorMap_t::iterator mapit=mapping->begin();
+			bool done=false;
+			while(!done) {
+				done=true;
+				for(mapit=mapping->begin(); mapit!=mapping->end(); mapit++) { // go through each sourceID vector
+					if((*mapit).second.size()==0) {
+						mapping->erase(mapit);
+						done=false;
+						break;
 					}
 				}
 			}
 		}
 	}
 	// now remove any empty mappings
-	for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) {
-		for(unsigned int et=0; et<EventBase::numETIDs; et++) {
-			SIDtoListenerVectorMap_t* mapping=filteredevents[eg][et];
-			if(mapping!=NULL) { // if there are subscribers to this egid/etid
-				if(mapping->size()==0) {
-					delete mapping;
-					filteredevents[eg][et]=NULL;
-				}
+	for(unsigned int et=0; et<EventBase::numETIDs; et++) {
+		SIDtoListenerVectorMap_t* mapping=filteredevents[egid][et];
+		if(mapping!=NULL) { // if there are subscribers to this egid/etid
+			if(mapping->size()==0) {
+				delete mapping;
+				filteredevents[egid][et]=NULL;
 			}
 		}
 	}
@@ -349,9 +533,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
- * $State: Rel $
- * $Date: 2003/10/03 03:41:01 $
+ * $Revision: 1.13 $
+ * $State: Exp $
+ * $Date: 2004/10/07 22:14:17 $
  */
 
 
Index: Events/EventRouter.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventRouter.h,v
retrieving revision 1.13
retrieving revision 1.16
diff -u -d -r1.13 -r1.16
--- Events/EventRouter.h	18 Jan 2004 10:16:57 -0000	1.13
+++ Events/EventRouter.h	7 Oct 2004 22:14:17 -0000	1.16
@@ -14,8 +14,13 @@
 
 //! This class will handle distribution of events as well as management of timers
 /*! Classes must inherit from EventListener and/or EventTrapper in order to
- *  receive events.\n
- *  Use the global @c ::erouter EventRouter to post and subscribe to events\n
+ *  receive events.
+ *
+ *  Use the global @c ::erouter EventRouter to post and subscribe to
+ *  events, except if you are posting from within a MotionCommand, in
+ *  which case you should use MotionCommand::postEvent() so that it
+ *  will automatically be sent from the Motion process to the Main
+ *  process.
  *
  *  When multiple listeners are subscribed, the order in which an event is
  *  distributed among them looks like this:
@@ -28,11 +33,32 @@
  *  ...but if you're relying on that ordering, there should be a cleaner
  *  way to do whatever you're doing.
  *
- *  If one behaviors unsubscribes another one during a processEvent(), that
- *  behavior will still get the "current" event before the unsubscription
- *  takes place.
+ *  If one behaviors unsubscribes another one during a processEvent(),
+ *  that behavior may still get the "current" event before the
+ *  unsubscription takes place.  This is not a prescribed behavior,
+ *  and also should not be relied on one way or the other.
  *
- *  Buffering events has not been tested thoroughly...
+ *  Timer events are only sent to the generator which requested them.  So if 
+ *  EventListener @e A requests a timer with ID 0 at two second intervals,
+ *  and EventListener @e B requests a timer with ID 0 at three second intervals,
+ *  each will still only receive the timers they requested - no cross talk.
+ *  The timer generator is unique in this regard, which is why it is built in
+ *  as an integral component of the EventRouter.  All other events are broadcast.
+ *
+ *  If an EventListener/EventTrapper subscribes to the same event source multiple
+ *  times, it will receive multiple copies of the event.  However, the first call
+ *  to removeListener for a source will remove all subscriptions to that source.\n
+ *  Example: EventListener @e A subscribes to (buttonEGID,*,*), and twice to
+ *  (buttonEGID,0,*).
+ *    - If button 0 is pressed, @e A will get three copies of the event.
+ *    - If button 1 is pressed, @e A will get one copy.
+ *    - If removeListener(&A,buttonEGID) is called, the (buttonEGID,*,*) is
+ *      removed, <em>as well as</em> both of (buttonEGID,0,*).
+ *    - If removeListener(&A,buttonEGID,0) is called, both of (buttonEGID,0,*)
+ *      are removed, but (buttonEGID,*,*) would be untouched.
+ *
+ *  The buffered event distribution has not been tested thoroughly,
+ *  and should be considered deprecated.
  *
  *  @see EventBase::EventGeneratorID_t for a complete listing of all generators,
  *  as well as instructions on how to add new generators.
@@ -67,10 +93,11 @@
 	bool hasListeners(EventBase::EventGeneratorID_t egid) { return trappers.hasMapping(egid) || listeners.hasMapping(egid); }
 	bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid) { return trappers.hasMapping(egid,sid) || listeners.hasMapping(egid,sid); }
 	bool hasListeners(EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { return trappers.hasMapping(egid,sid,etid) || listeners.hasMapping(egid,sid,etid); }
+	bool hasListeners(const EventBase& e) { return hasListeners(e.getGeneratorID(),e.getSourceID(),e.getTypeID()); }
 	//@}
 
 	//!@name Timer Management
-	void addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat=true); //!< adds a timer or sets a timer if it doesn't already exist.
+	void addTimer(EventListener* el, unsigned int sid, unsigned int delay, bool repeat=true); //!< adds a timer if it doesn't exist, or resets the timer if it already exists.
 	void addTimer(EventListener* el, const EventBase& e, bool repeat=true) { addTimer(el,e.getSourceID(),e.getDuration(),repeat); } //!< calls the other addTimer() with the event's source id and duration, doesn't check to see if the generator is timerEGID
 	void removeTimer(EventListener* el); //!< clears all pending timers for listener @a el
 	void removeTimer(EventListener* el, unsigned int sid); //!< clears any pending timers with source id @a sid for listener @a el
@@ -78,36 +105,44 @@
 	//@}
 
 	//!@name Listener Management
-	void addListener(EventListener* el, const EventBase& e); //!< Adds a listener for a specific source id and type from a given event generator, adding a Timer event will invoke addTimer(@a el, @a e.getSourceID(), @a e.getDuration(), @c true)
-	void addListener(EventListener* el, EventBase::EventGeneratorID_t egid); //!< Adds a listener for all events from a given event generator
+	//! Adds a listener for all events from a given event generator
+	void addListener(EventListener* el, EventBase::EventGeneratorID_t egid);
 	void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< Adds a listener for all types from a specific source and generator
 	void addListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a listener for a specific source id and type from a given event generator
+	//! Adds a listener for a specific source id and type from a given event generator, adding a Timer event will invoke addTimer(@a el, @a e.getSourceID(), @a e.getDuration(), @c true)
+	void addListener(EventListener* el, const EventBase& e); 
 
+	//! stops sending ALL events to the listener, including timers
+	void removeListener(EventListener* el); 
+	//! stops sending specified events from the generator to the listener.
+	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid);
+	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the listener.
+	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< stops sending specified events from the generator to the listener.
 	//! stops sending specified events from the generator to the listener.  If a timer is passed it will invoke removeTimer(@a el, @a e.getSourceID())
 	void removeListener(EventListener* el, const EventBase& e);
-	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid) { listeners.removeMapping(el,egid); listeners.clean(); } //!< stops sending specified events from the generator to the listener.
-	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) listeners.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et); listeners.clean(); } //!< stops sending specified events from the generator to the listener.
-	void removeListener(EventListener* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { listeners.removeMapping(el,egid,sid,etid); listeners.clean(); } //!< stops sending specified events from the generator to the listener.
 
-	void removeListener(EventListener* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) listeners.removeMapping(el,(EventBase::EventGeneratorID_t)eg); listeners.clean(); } //!< stops sending ALL events to the listener
-	void forgetListener(EventListener* el) { removeTimer(el); removeListener(el); } //!< clears timers and removes listener from all events
+	/*! @deprecated use removeListener(EventListener* el) instead
+	 *  @brief deprecated, you should call removeListener(EventListener* el) instead */
+	void forgetListener(EventListener* el) __attribute__((deprecated));
 	//@}
 
 	//!@name Trapper Management
-	void addTrapper(EventTrapper* el, const EventBase& e) { trappers.addMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); } //!< Adds a trapper for a specific source id and type from a given event generator
-	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) { trappers.addMapping(el,egid); } //!< Adds a trapper for all events from a given event generator
-	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) trappers.addMapping(el,egid,sid,(EventBase::EventTypeID_t)et); }  //!< Adds a trapper for all types from a specific source and generator
-	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { trappers.addMapping(el,egid,sid,etid); } //!< Adds a trapper for a specific source id and type from a given event generator
+	//! Adds a trapper for a specific source id and type from a given event generator
+	/*! Note that since timers are not broadcast, they cannot be trapped.  Only the EventListener which requested the timer will receive that timer. */
+	void addTrapper(EventTrapper* el, const EventBase& e);
+	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< Adds a trapper for all events from a given event generator
+	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid);  //!< Adds a trapper for all types from a specific source and generator
+	void addTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a trapper for a specific source id and type from a given event generator
 
-	void addTrapper(EventTrapper* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) trappers.addMapping(el,(EventBase::EventGeneratorID_t)eg); } //!< adds a trapper for ALL events
+	void addTrapper(EventTrapper* el); //!< adds a trapper for ALL events
 
 	//! stops sending specified events from the generator to the trapper.
-	void removeTrapper(EventTrapper* el, const EventBase& e) { trappers.removeMapping(el,e.getGeneratorID(),e.getSourceID(),e.getTypeID()); trappers.clean(); }
-	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid) { trappers.removeMapping(el,egid); trappers.clean(); } //!< stops sending specified events from the generator to the trapper.
-	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid) { for(unsigned int et=0; et<EventBase::numETIDs; et++) trappers.removeMapping(el,egid,sid,(EventBase::EventTypeID_t)et); trappers.clean(); } //!< stops sending specified events from the generator to the trapper.
-	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid) { trappers.removeMapping(el,egid,sid,etid); trappers.clean(); } //!< stops sending specified events from the generator to the trapper.
+	void removeTrapper(EventTrapper* el, const EventBase& e);
+	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid); //!< stops sending specified events from the generator to the trapper.
+	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid); //!< stops sending specified events from the generator to the trapper.
+	void removeTrapper(EventTrapper* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< stops sending specified events from the generator to the trapper.
 
-	void removeTrapper(EventTrapper* el) { for(unsigned int eg=0; eg<EventBase::numEGIDs; eg++) trappers.removeMapping(el,(EventBase::EventGeneratorID_t)eg); trappers.clean(); } //!< stops sending ALL events to the trapper
+	void removeTrapper(EventTrapper* el); //!< stops sending ALL events to the trapper
 	//@}
 
  protected:
@@ -193,15 +228,16 @@
 		void addMapping(void* el, EventBase::EventGeneratorID_t egid) { allevents[egid].push_back(el); } //!< Adds a listener for all events from a given event generator
 		void addMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid); //!< Adds a listener for a specific source id and type from a given event generator
 
-		//! Removes a listener for all events from a given event generator
+		//! Removes a listener for all events from a given event generator, returns true if something was actually removed
 		/*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */
-		void removeMapping(void* el, EventBase::EventGeneratorID_t egid); 
+		bool removeMapping(void* el, EventBase::EventGeneratorID_t egid); 
 
-		//! Removes a listener for a specific source id and type from a given event generator
+		//! Removes a listener for a specific source id and type from a given event generator, returns true if something was actually removed
 		/*! Doesn't necessarily remove the vector or mapping if this was the last listener, use clean() to do that */
-		void removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid);
+		bool removeMapping(void* el, EventBase::EventGeneratorID_t egid, unsigned int sid, EventBase::EventTypeID_t etid);
 
-		void clean(); //!<compresses empty data structures
+		void clean(); //!<removes empty data structures for all event generators
+		void clean(EventBase::EventGeneratorID_t egid); //!< removes empty data structures associated with a single event generator
 		void clear(); //!<Resets the mapping
 
 		//@{
@@ -264,9 +300,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.13 $
+ * $Revision: 1.16 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:57 $
+ * $Date: 2004/10/07 22:14:17 $
  */
 
 #endif
Index: Events/EventTranslator.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventTranslator.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Events/EventTranslator.cc	22 Nov 2003 20:33:01 -0000	1.6
+++ Events/EventTranslator.cc	14 Oct 2004 23:02:35 -0000	1.7
@@ -28,7 +28,7 @@
 	}
 	void* buf=q->reserve(sizeof(TypeID_t)+len);
 	if(buf==NULL) {
-		ASSERT(false,"Queue overflow");
+		ASSERT(false,"Queue overflow "<<type<<' '<<len);
 	} else {
 		*reinterpret_cast<TypeID_t*>(buf)=type;
 		reinterpret_cast<char*>(buf)+=sizeof(TypeID_t);
@@ -87,8 +87,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
  * $State: Exp $
- * $Date: 2003/11/22 20:33:01 $
+ * $Date: 2004/10/14 23:02:35 $
  */
 
Index: Events/EventTranslator.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/EventTranslator.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Events/EventTranslator.h	22 Nov 2003 20:33:01 -0000	1.4
+++ Events/EventTranslator.h	16 Sep 2004 18:35:12 -0000	1.5
@@ -39,6 +39,9 @@
 	//!called by trapEvent to do all the work, needed so MotionCommands can enqueue directly
 	static void enqueue(const EventBase& event, Queue_t * q);
 
+	//!called by non-MotionCommands to enqueue an event
+	void enqueue(const EventBase& event) { enqueue(event,queue); }
+
 	//!called whenever Main gets some processor time to check for events from other processes
 	void translateEvents();
 
@@ -60,9 +63,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2003/11/22 20:33:01 $
+ * $Date: 2004/09/16 18:35:12 $
  */
 
 #endif
Index: Events/LocomotionEvent.cc
===================================================================
RCS file: Events/LocomotionEvent.cc
diff -N Events/LocomotionEvent.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Events/LocomotionEvent.cc	1 Sep 2004 21:30:57 -0000	1.1
@@ -0,0 +1,67 @@
+#include "LocomotionEvent.h"
+#include <sstream>
+
+std::string
+LocomotionEvent::getDescription(bool showTypeSpecific/*=true*/, unsigned int verbosity/*=0*/) const {
+	if(!showTypeSpecific)
+		return EventBase::getDescription(showTypeSpecific,verbosity);
+	std::ostringstream logdata;
+	logdata << EventBase::getDescription(showTypeSpecific,verbosity) << '\t' << x << '\t' << y << '\t' << a;
+	return logdata.str();
+}
+	
+unsigned int
+LocomotionEvent::getBinSize() const {
+	unsigned int used=EventBase::getBinSize();
+	used+=creatorSize("EventBase::LocomotionEvent");
+	used+=sizeof(x);
+	used+=sizeof(y);
+	used+=sizeof(a);
+	return used;
+}
+
+unsigned int
+LocomotionEvent::LoadBuffer(const char buf[], unsigned int len) {
+	unsigned int origlen=len;
+	unsigned int used;
+	if(0==(used=EventBase::LoadBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=checkCreator("EventBase::LocomotionEvent",buf,len,true))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=decode(x,buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=decode(y,buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=decode(a,buf,len))) return 0;
+	len-=used; buf+=used;
+	return origlen-len;	
+}
+
+unsigned int
+LocomotionEvent::SaveBuffer(char buf[], unsigned int len) const {
+	unsigned int origlen=len;
+	unsigned int used;
+	if(0==(used=EventBase::SaveBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=saveCreator("EventBase::LocomotionEvent",buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=encode(x,buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=encode(y,buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=encode(a,buf,len))) return 0;
+	len-=used; buf+=used;
+	return origlen-len;
+}
+
+
+/*! @file
+ * @brief Implements LocomotionEvent, which gives updates regarding the current movement of the robot through the world
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/09/01 21:30:57 $
+ */
Index: Events/LocomotionEvent.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/LocomotionEvent.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Events/LocomotionEvent.h	25 Sep 2003 15:27:10 -0000	1.5
+++ Events/LocomotionEvent.h	1 Sep 2004 21:30:57 -0000	1.6
@@ -28,47 +28,12 @@
 		a=A;
 		return *this;
 	}
-	
-	virtual unsigned int getBinSize() const {
-		unsigned int used=EventBase::getBinSize();
-		used+=creatorSize("EventBase::LocomotionEvent");
-		used+=sizeof(x);
-		used+=sizeof(y);
-		used+=sizeof(a);
-		return used;
-	}
 
-	virtual unsigned int LoadBuffer(const char buf[], unsigned int len) {
-		unsigned int origlen=len;
-		unsigned int used;
-		if(0==(used=EventBase::LoadBuffer(buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=checkCreator("EventBase::LocomotionEvent",buf,len,true))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=decode(x,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=decode(y,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=decode(a,buf,len))) return 0;
-		len-=used; buf+=used;
-		return origlen-len;	
-	}
+	virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const;
 
-	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const {
-		unsigned int origlen=len;
-		unsigned int used;
-		if(0==(used=EventBase::SaveBuffer(buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=saveCreator("EventBase::LocomotionEvent",buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=encode(x,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=encode(y,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=encode(a,buf,len))) return 0;
-		len-=used; buf+=used;
-		return origlen-len;
-	}
+	virtual unsigned int getBinSize() const;
+	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
+	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
 
 	float x; //!< the new x component (body relative)
 	float y; //!< the new y component (body relative)
@@ -76,14 +41,14 @@
 };
 
 /*! @file
- * @brief Defines LocomotionEvent, which gives updates regarding the current movement of the robot through the world
+ * @brief Describes LocomotionEvent, which gives updates regarding the current movement of the robot through the world
  * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
- * $State: Rel $
- * $Date: 2003/09/25 15:27:10 $
+ * $Revision: 1.6 $
+ * $State: Exp $
+ * $Date: 2004/09/01 21:30:57 $
  */
 
 #endif
Index: Events/TextMsgEvent.cc
===================================================================
RCS file: Events/TextMsgEvent.cc
diff -N Events/TextMsgEvent.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Events/TextMsgEvent.cc	1 Sep 2004 21:30:57 -0000	1.1
@@ -0,0 +1,61 @@
+#include "TextMsgEvent.h"
+#include <sstream>
+
+std::string
+TextMsgEvent::getDescription(bool showTypeSpecific/*=true*/, unsigned int verbosity/*=0*/) const {
+	if(!showTypeSpecific)
+		return EventBase::getDescription(showTypeSpecific,verbosity);
+	std::ostringstream logdata;
+	logdata << EventBase::getDescription(showTypeSpecific,verbosity) << '\t' << _text;
+	return logdata.str();
+}
+
+unsigned int
+TextMsgEvent::getBinSize() const {
+	unsigned int used=EventBase::getBinSize();
+	used+=creatorSize("EventBase::TextMsgEvent");
+	used+=_text.size()+stringpad;
+	//used+=sizeof(_token);
+	return used;
+}
+
+unsigned int
+TextMsgEvent::LoadBuffer(const char buf[], unsigned int len) {
+	unsigned int origlen=len;
+	unsigned int used;
+	if(0==(used=EventBase::LoadBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=checkCreator("EventBase::TextMsgEvent",buf,len,true))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=decode(_text,buf,len))) return 0;
+	len-=used; buf+=used;
+	//if(0==(used=decode(_token,buf,len))) return 0;
+	//len-=used; buf+=used;
+	return origlen-len;	
+}
+
+unsigned int
+TextMsgEvent::SaveBuffer(char buf[], unsigned int len) const {
+	unsigned int origlen=len;
+	unsigned int used;
+	if(0==(used=EventBase::SaveBuffer(buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=saveCreator("EventBase::TextMsgEvent",buf,len))) return 0;
+	len-=used; buf+=used;
+	if(0==(used=encode(_text,buf,len))) return 0;
+	len-=used; buf+=used;
+	//if(0==(used=encode(_token,buf,len))) return 0;
+	//len-=used; buf+=used;
+	return origlen-len;
+}
+
+/*! @file
+ * @brief Implements TextMsgEvent, which extends EventBase to also include actual message text
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/09/01 21:30:57 $
+ */
Index: Events/TextMsgEvent.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/TextMsgEvent.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Events/TextMsgEvent.h	5 Dec 2003 20:26:42 -0000	1.9
+++ Events/TextMsgEvent.h	1 Sep 2004 21:30:57 -0000	1.10
@@ -8,67 +8,37 @@
 class TextMsgEvent : public EventBase {
  public:
 	//! Constructor
-  TextMsgEvent() : EventBase(EventBase::textmsgEGID,(unsigned int)-1, EventBase::statusETID,0),_text(""),_token(0) {  }
+  TextMsgEvent() : EventBase(EventBase::textmsgEGID,(unsigned int)-1, EventBase::statusETID,0),_text("")/*,_token(0)*/ {  }
 
   //! Constructor, pass a text msg
-  TextMsgEvent(const std::string& text) : EventBase(EventBase::textmsgEGID,(unsigned int)-1, EventBase::statusETID,0),_text(text),_token(0) { }
+  TextMsgEvent(const std::string& text) : EventBase(EventBase::textmsgEGID,(unsigned int)-1, EventBase::statusETID,0),_text(text)/*,_token(0)*/ { }
   
   std::string getText() const { return _text; } //!< returns the text
   TextMsgEvent& setText(const std::string& text) { _text=text; return *this; } //!< sets the text
   
-  int getToken() const { return _token; } //!< returns the token
-  TextMsgEvent& setToken(int token) { _token=token; return *this;} //!< sets the token
-      
-	virtual unsigned int getBinSize() const {
-		unsigned int used=EventBase::getBinSize();
-		used+=creatorSize("EventBase::TextMsgEvent");
-		used+=_text.size()+stringpad;
-		used+=sizeof(_token);
-		return used;
-	}
-
-	virtual unsigned int LoadBuffer(const char buf[], unsigned int len) {
-		unsigned int origlen=len;
-		unsigned int used;
-		if(0==(used=EventBase::LoadBuffer(buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=checkCreator("EventBase::TextMsgEvent",buf,len,true))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=decode(_text,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=decode(_token,buf,len))) return 0;
-		len-=used; buf+=used;
-		return origlen-len;	
-	}
-
-	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const {
-		unsigned int origlen=len;
-		unsigned int used;
-		if(0==(used=EventBase::SaveBuffer(buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=saveCreator("EventBase::TextMsgEvent",buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=encode(_text,buf,len))) return 0;
-		len-=used; buf+=used;
-		if(0==(used=encode(_token,buf,len))) return 0;
-		len-=used; buf+=used;
-		return origlen-len;
-	}
+  //int getToken() const { return _token; } //!< returns the token
+  //TextMsgEvent& setToken(int token) { _token=token; return *this;} //!< sets the token
+	
+	std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const;
+	
+	virtual unsigned int getBinSize() const;
+	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
+	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
 
  protected:
   std::string _text; //!< the unmodified arguments passed to the command
-  int _token;      //!< for future expansion, to support centralized parsing
+  //int _token;      //!< for future expansion, to support centralized parsing
 };
 
 /*! @file
- * @brief Defines TextMsgEvent, which extends EventBase to also include actual message text
+ * @brief Describes TextMsgEvent, which extends EventBase to also include actual message text
  * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.10 $
  * $State: Exp $
- * $Date: 2003/12/05 20:26:42 $
+ * $Date: 2004/09/01 21:30:57 $
  */
 
 #endif
Index: Events/VisionObjectEvent.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/VisionObjectEvent.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Events/VisionObjectEvent.cc	8 Dec 2003 00:21:05 -0000	1.2
+++ Events/VisionObjectEvent.cc	1 Sep 2004 21:30:57 -0000	1.3
@@ -1,4 +1,14 @@
 #include "VisionObjectEvent.h"
+#include <sstream>
+
+std::string
+VisionObjectEvent::getDescription(bool showTypeSpecific/*=true*/, unsigned int verbosity/*=0*/) const {
+	if(!showTypeSpecific)
+		return EventBase::getDescription(showTypeSpecific,verbosity);
+	std::ostringstream logdata;
+	logdata << EventBase::getDescription(showTypeSpecific,verbosity) << '\t' << _cenX << '\t' << _cenY;
+	return logdata.str();
+}
 
 unsigned int
 VisionObjectEvent::getBinSize() const {
@@ -6,7 +16,7 @@
 	used+=creatorSize("EventBase::VisionObjectEvent");
 	used+=sizeof(_cenX);
 	used+=sizeof(_cenY);
-	used+=sizeof(_distance);
+	//used+=sizeof(_distance);
 	//used+=sizeof(_property);
 	return used;
 }
@@ -23,8 +33,8 @@
 	len-=used; buf+=used;
 	if(0==(used=decode(_cenY,buf,len))) return 0;
 	len-=used; buf+=used;
-	if(0==(used=decode(_distance,buf,len))) return 0;
-	len-=used; buf+=used;
+	//if(0==(used=decode(_distance,buf,len))) return 0;
+	//len-=used; buf+=used;
 	//if(0==(used=decode(_property,buf,len))) return 0;
 	//len-=used; buf+=used;
 	return origlen-len;	
@@ -42,8 +52,8 @@
 	len-=used; buf+=used;
 	if(0==(used=encode(_cenY,buf,len))) return 0;
 	len-=used; buf+=used;
-	if(0==(used=encode(_distance,buf,len))) return 0;
-	len-=used; buf+=used;
+	//if(0==(used=encode(_distance,buf,len))) return 0;
+	//len-=used; buf+=used;
 	//if(0==(used=encode(_property,buf,len))) return 0;
 	//len-=used; buf+=used;
 	return origlen-len;
Index: Events/VisionObjectEvent.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Events/VisionObjectEvent.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Events/VisionObjectEvent.h	8 Dec 2003 00:21:05 -0000	1.2
+++ Events/VisionObjectEvent.h	1 Sep 2004 21:30:57 -0000	1.3
@@ -8,11 +8,11 @@
 class VisionObjectEvent : public EventBase {
  public:
 	//! Constructor
-  VisionObjectEvent() : EventBase(EventBase::visObjEGID,(unsigned int)-1,EventBase::statusETID,0),_cenX(0),_cenY(0),_distance()/*,_property(-1)*/ {}
+  VisionObjectEvent() : EventBase(EventBase::visObjEGID,(unsigned int)-1,EventBase::statusETID,0),_cenX(0),_cenY(0)/*,_distance(),_property(-1)*/ {}
 	//! Constructor, pass a type id and source id
-  VisionObjectEvent(EventTypeID_t tid, unsigned int sid) : EventBase(EventBase::visObjEGID,sid,tid,0),_cenX(0),_cenY(0),_distance()/*,_property(-1)*/ {}
+  VisionObjectEvent(EventTypeID_t tid, unsigned int sid) : EventBase(EventBase::visObjEGID,sid,tid,0),_cenX(0),_cenY(0)/*_distance(),_property(-1)*/ {}
 	//! Constructor, pass the type id, source id, center X and center Y
-  VisionObjectEvent(EventTypeID_t tid, unsigned int sid, float cenX, float cenY) : EventBase(EventBase::visObjEGID,sid,tid,0),_cenX(cenX),_cenY(cenY),_distance()/*,_property(-1)*/ {}
+  VisionObjectEvent(EventTypeID_t tid, unsigned int sid, float cenX, float cenY) : EventBase(EventBase::visObjEGID,sid,tid,0),_cenX(cenX),_cenY(cenY)/*,_distance(),_property(-1)*/ {}
 	//! destructor
 	virtual ~VisionObjectEvent() {}
   
@@ -22,12 +22,14 @@
   float getCenterY() const { return _cenY;} //!< returns the y coordinate
   VisionObjectEvent& setCenterY(float cenY) { _cenY=cenY; return *this;} //!< sets the y coordinate
 
-  float getDistance() const { return _distance;} //!< returns the distance (not implemented)
-  VisionObjectEvent& setDistance(float dist) { _distance=dist; return *this;} //!< sets the distance
+  //float getDistance() const { return _distance;} //!< returns the distance (not implemented)
+  //VisionObjectEvent& setDistance(float dist) { _distance=dist; return *this;} //!< sets the distance
 
   //int getProperty() const { return _property;} //!< returns the property (for future use)
   //VisionObjectEvent& setProperty(int property) { _property=property; return *this;} //!< sets the property
       
+	virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const;
+	
 	virtual unsigned int getBinSize() const;
 	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
 	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
@@ -35,7 +37,7 @@
  protected:
 	float _cenX; //!< a value representing location in visual field - from -1 if on the left edge to 1 if it's on the right edge
 	float _cenY; //!< a value representing location in visual field - from -1 if on the bottom edge to 1 if it's on the top edge
-	float _distance; //!< distance from snout to object in millimeters. (not implemented)
+	//float _distance; //!< distance from snout to object in millimeters. (not implemented)
   //int _property; //!< some property, depending on the SID (for future use)
 };
 
@@ -45,9 +47,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * $State: Exp $
- * $Date: 2003/12/08 00:21:05 $
+ * $Date: 2004/09/01 21:30:57 $
  */
 
 #endif
Index: MMCombo/MMCombo.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/MMCombo/MMCombo.cc,v
retrieving revision 1.50
retrieving revision 1.57
diff -u -d -r1.50 -r1.57
--- MMCombo/MMCombo.cc	3 Mar 2004 03:37:03 -0000	1.50
+++ MMCombo/MMCombo.cc	11 Oct 2004 22:00:19 -0000	1.57
@@ -8,6 +8,7 @@
 #include "Events/EventRouter.h"
 #include "Behaviors/BehaviorBase.h"
 #include "Motion/MotionManager.h"
+#include "Motion/Kinematics.h"
 #include "SoundPlay/SoundManager.h"
 #include "Events/DataEvent.h"
 #include "Events/TextMsgEvent.h"
@@ -53,9 +54,28 @@
 	// make sure the library doesn't drop data "for" us on this reliable communication channel
 	observer[obsReceiveWorldState]->SetBufCtrlParam(0,1,1);
 	observer[obsReceiveMotionManager]->SetBufCtrlParam(0,1,1);
+	observer[obsReceiveSoundManager]->SetBufCtrlParam(0,1,1);
 	observer[obsMotionManagerComm]->SetBufCtrlParam(0,1,MotionManager::MAX_MOTIONS+1);
 	//+1 to MAX_MOTIONS so we can get a delete message after we've filled up
 
+	cout << objectName << ": sbjRegisterWorldState==" << sbjRegisterWorldState << " selector==" << subject[sbjRegisterWorldState]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsReceiveWorldState==" << obsReceiveWorldState << " selector==" << observer[obsReceiveWorldState]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjRegisterMotionManager==" << sbjRegisterMotionManager << " selector==" << subject[sbjRegisterMotionManager]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsReceiveMotionManager==" << obsReceiveMotionManager << " selector==" << observer[obsReceiveMotionManager]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjRegisterEventTranslatorQueue==" << sbjRegisterEventTranslatorQueue << " selector==" << subject[sbjRegisterEventTranslatorQueue]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsReceiveEventTranslatorQueue==" << obsReceiveEventTranslatorQueue << " selector==" << observer[obsReceiveEventTranslatorQueue]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjMoveJoint==" << sbjMoveJoint << " selector==" << subject[sbjMoveJoint]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsSensorFrame==" << obsSensorFrame << " selector==" << observer[obsSensorFrame]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsImage==" << obsImage << " selector==" << observer[obsImage]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsMic==" << obsMic << " selector==" << observer[obsMic]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjMotionManagerComm==" << sbjMotionManagerComm << " selector==" << subject[sbjMotionManagerComm]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsMotionManagerComm==" << obsMotionManagerComm << " selector==" << observer[obsMotionManagerComm]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsReceiveSoundManager==" << obsReceiveSoundManager << " selector==" << observer[obsReceiveSoundManager]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjSoundManagerComm==" << sbjSoundManagerComm << " selector==" << subject[sbjSoundManagerComm]->GetID().GetSelector() << '\n'
+			 << objectName << ": sbjRPOPENRSendString==" << sbjRPOPENRSendString << " selector==" << subject[sbjRPOPENRSendString]->GetID().GetSelector() << '\n'
+			 << objectName << ": obsRPOPENRReceiveString==" << obsRPOPENRReceiveString << " selector==" << observer[obsRPOPENRReceiveString]->GetID().GetSelector() << '\n'
+			 << flush;
+
 	if(strcmp(objectName,"MainObj")==0)
 		ProcessID::setID(ProcessID::MainProcess);
 	else if(strcmp(objectName,"MotoObj")==0)
@@ -82,7 +102,7 @@
 			OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::DoStart()","OPENR::ObservePowerStatus() FAILED", result));
 			return oFAIL;
 		}
-
+		
     //Setup wireless
     wireless = new Wireless();
     sout=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*6);
@@ -109,11 +129,23 @@
     OPENR::SetMotorPower(opowerON);
 		OPENR::EnableJointGain(oprimitiveID_UNDEF); //oprimitiveID_UNDEF means enable all
 
+    //Setup wireless
+    wireless = new Wireless();
+    sout=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*6);
+    serr=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*2);
+    wireless->setDaemon(sout);
+    wireless->setDaemon(serr);
+		serr->setFlushType(SocketNS::FLUSH_BLOCKING);
+    sout->setTextForward();
+    serr->setForward(sout);
+		
 		//motmanMemRgn -> motman setup
 		motmanMemRgn = InitRegion(sizeof(MotionManager));
 		motman = new (motmanMemRgn->Base()) MotionManager();
 		motman->InitAccess(subject[sbjMotionManagerComm]);
 	}
+	kine = new Kinematics();
+
 	ProjectInterface::startupBehavior.AddReference();
 
 	cout << objectName << "::DoInit()-DONE" << endl;
@@ -135,6 +167,11 @@
 		state->read(power,erouter);
 	}
 
+	if(strcmp(objectName,"MotoObj")==0) {
+		wireless->listen(sout, config->motion.console_port);
+		wireless->listen(serr, config->motion.stderr_port);
+	}
+	
 	isStopped=false;
 
 	ENABLE_ALL_SUBJECT;
@@ -475,6 +512,8 @@
 	PROFSECTION("GotImage()",state->mainProfile);
 	etrans.translateEvents();
 
+  erouter->processTimers();
+  
 	WMvari(int, frame_counter, 0);
 	++frame_counter;
 	
@@ -486,6 +525,23 @@
 }
 
 void
+MMCombo::GotAudio(const ONotifyEvent& event){
+	if(isStopped) {
+		//cout << "BAH!GotAudio" << endl;
+		return;
+	}
+
+	PROFSECTION("GotAudio()",state->mainProfile);
+	etrans.translateEvents();
+
+	erouter->postEvent(new DataEvent<const OSoundVectorData*>(reinterpret_cast<const OSoundVectorData*>(event.Data(0)),EventBase::micOSndEGID,0,EventBase::statusETID));
+	
+  erouter->processTimers();
+  
+  observer[obsMic]->AssertReady();
+}
+
+void
 MMCombo::GotPowerEvent(void * msg){
 	if(isStopped) {
 		//cout << "BAH!GotPowerEvent" << endl;
@@ -712,9 +768,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.50 $
+ * $Revision: 1.57 $
  * $State: Exp $
- * $Date: 2004/03/03 03:37:03 $
+ * $Date: 2004/10/11 22:00:19 $
  */
 
 
Index: MMCombo/MMCombo.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/MMCombo/MMCombo.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- MMCombo/MMCombo.h	3 Feb 2004 01:17:24 -0000	1.25
+++ MMCombo/MMCombo.h	28 Sep 2004 23:07:04 -0000	1.26
@@ -51,6 +51,9 @@
 	void ReadySendJoints(const OReadyEvent& event);      //!< motion only (until main does ears again, then both) calls SendJoints, if DoStart has already been called
 	void GotSensorFrame(const ONotifyEvent& event);      //!< main only, called when new sensor information is available
 	void GotImage(const ONotifyEvent& event);            //!< main only, called when a new image is available
+// paris start
+	void GotAudio(const ONotifyEvent& event);            //!< main only, called when a new audio buffer is available
+// paris end
 	void GotPowerEvent(void * msg);                      //!< main only, called when a power event occurs (can be just status events)
 	
 	void GotMotionMsg(const ONotifyEvent& event);        //!< both, called when a new MotionManagerMsg has been received
@@ -139,9 +142,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.25 $
+ * $Revision: 1.26 $
  * $State: Exp $
- * $Date: 2004/02/03 01:17:24 $
+ * $Date: 2004/09/28 23:07:04 $
  */
 
 #endif
Index: MMCombo/stub.cfg
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/MMCombo/stub.cfg,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- MMCombo/stub.cfg	6 Apr 2003 20:57:44 -0000	1.6
+++ MMCombo/stub.cfg	28 Sep 2004 23:07:04 -0000	1.7
@@ -1,6 +1,6 @@
 ObjectName : MMCombo
 NumOfSubject   : 7
-NumOfObserver  : 8
+NumOfObserver  : 9
 Service : "MMCombo.RegisterWorldState.WorldState.S"          , null, ReadyRegisterWorldState()
 Service : "MMCombo.ReceiveWorldState.WorldState.O"           , null, GotWorldState()
 Service : "MMCombo.RegisterMotionManager.MotionManager.S"    , null, ReadyRegisterMotionManager()
@@ -10,6 +10,7 @@
 Service : "MMCombo.MoveJoint.OCommandVectorData.S"           , null, ReadySendJoints()
 Service : "MMCombo.SensorFrame.OSensorFrameVectorData.O"     , null, GotSensorFrame()
 Service : "MMCombo.Image.OFbkImageVectorData.O"              , null, GotImage()
+Service : "MMCombo.Mic.OSoundVectorData.O"                   , null, GotAudio()
 Service : "MMCombo.MotionManagerComm.MotionManagerMsg.S"     , null, null
 Service : "MMCombo.MotionManagerComm.MotionManagerMsg.O"     , null, GotMotionMsg()
 Service : "MMCombo.ReceiveSoundManager.SoundManager.O"       , null, GotSoundManager()
Index: Motion/EmergencyStopMC.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/EmergencyStopMC.cc,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- Motion/EmergencyStopMC.cc	6 Feb 2004 23:13:46 -0000	1.20
+++ Motion/EmergencyStopMC.cc	30 Aug 2004 20:26:45 -0000	1.21
@@ -105,6 +105,12 @@
 	dirty=true;
 }
 
+void EmergencyStopMC::takeSnapshot(const WorldState* st) {
+	for(unsigned int i=0; i<NumOutputs; i++)
+		cmds[i].value=st->outputs[i];
+	dirty=true;
+}
+
 void EmergencyStopMC::setActive(bool a) {
 	if(paused) {
 		if(!a && active)
@@ -204,8 +210,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.20 $
+ * $Revision: 1.21 $
  * $State: Exp $
- * $Date: 2004/02/06 23:13:46 $
+ * $Date: 2004/08/30 20:26:45 $
  */
 
Index: Motion/EmergencyStopMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/EmergencyStopMC.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Motion/EmergencyStopMC.h	18 Jan 2004 10:16:57 -0000	1.10
+++ Motion/EmergencyStopMC.h	30 Aug 2004 20:26:45 -0000	1.11
@@ -28,6 +28,7 @@
 	virtual int updateOutputs(); //!< checks for feedback or double tap
 
 	virtual void takeSnapshot(); //!< records current positions of joints
+	virtual void takeSnapshot(const WorldState* st); //!< records current positions of joints
 
 	void setActive(bool a); //!< allows you to modify #active
 	bool getActive() { return active; } //!< returns #active
@@ -62,9 +63,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
+ * $Revision: 1.11 $
  * $State: Exp $
- * $Date: 2004/01/18 10:16:57 $
+ * $Date: 2004/08/30 20:26:45 $
  */
 
 #endif
Index: Motion/HeadPointerMC.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/HeadPointerMC.cc,v
retrieving revision 1.9
retrieving revision 1.14
diff -u -d -r1.9 -r1.14
--- Motion/HeadPointerMC.cc	19 Jan 2004 07:56:16 -0000	1.9
+++ Motion/HeadPointerMC.cc	14 Oct 2004 21:59:23 -0000	1.14
@@ -5,28 +5,14 @@
 #include <math.h>
 #include "Shared/Config.h"
 
-HeadPointerMC::HeadPointerMC() :
-	MotionCommand(), dirty(true), active(true) {
+HeadPointerMC::HeadPointerMC()
+	: MotionCommand(), dirty(true), targetReached(false),
+	  headkin(::config->motion.makePath(::config->motion.kinematics),"Camera")
+{
 	setWeight(1);
 	defaultMaxSpeed();
-	for(unsigned int i=0; i<NumHeadJoints; i++) {
-		headModes[i]=BodyRelative;
-		headValues[i]=0;
-		headJoints[i].value=state->outputs[HeadOffset+i];
-	}
-}
-
-void HeadPointerMC::setJoints(double tilt, double pan, double roll) {
-	headValues[TiltOffset]=tilt;
-	headValues[PanOffset]=pan;
-	headValues[RollOffset]=roll;
-	dirty=true;
-}
-
-void HeadPointerMC::setWeight(double w) {
-	for(unsigned int x=0; x<NumHeadJoints; x++)
-		headJoints[x].weight=w;
-	dirty=true;
+	for(unsigned int i=0; i<NumHeadJoints; i++)
+		headTargets[i]=headCmds[i].value=state->outputs[HeadOffset+i];
 }
 
 void HeadPointerMC::defaultMaxSpeed() {
@@ -35,16 +21,50 @@
 	maxSpeed[RollOffset]=config->motion.max_head_roll_speed*FrameTime/1000;
 }
 
-void HeadPointerMC::setMode(CoordFrame_t m, bool conv) {
+void HeadPointerMC::setWeight(float w) {
 	for(unsigned int x=0; x<NumHeadJoints; x++)
-		setJointMode((RobotInfo::TPROffset_t)x,m,conv);
+		headCmds[x].weight=w;
+	markDirty();
 }
 
-void HeadPointerMC::setJointMode(RobotInfo::TPROffset_t i, CoordFrame_t m, bool conv) {
-	if(conv)
-		headValues[i]=HeadPointerMC::convert(i,headValues[i],headModes[i],m);
-	headModes[i]=m;
-	dirty=true;
+void HeadPointerMC::setJoints(float j1, float j2, float j3) {
+	headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,j1);
+	headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,j2);
+	headTargets[RollOffset]=clipAngularRange(HeadOffset+RollOffset,j3);
+	markDirty();
+}
+
+bool HeadPointerMC::lookAtPoint(float x, float y, float z) {
+	NEWMAT::ColumnVector Pobj(4),Plink(4);
+	Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=1;
+	Plink=0; Plink(3)=1;
+	bool conv=false;
+	NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
+	for(unsigned int i=0; i<NumHeadJoints; i++)
+		setJointValue(i,headkin.get_q(2+i));
+	return conv;
+}
+	
+bool HeadPointerMC::lookAtPoint(float x, float y, float z, float d) {
+	NEWMAT::ColumnVector Pobj(4),Plink(4);
+	Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=1;
+	Plink=0; Plink(3)=d; Plink(4)=1;
+	bool conv=false;
+	NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
+	for(unsigned int i=0; i<NumHeadJoints; i++)
+		setJointValue(i,headkin.get_q(2+i));
+	return conv;
+}
+	
+bool HeadPointerMC::lookInDirection(float x, float y, float z) {
+	NEWMAT::ColumnVector Pobj(4),Plink(4);
+	Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=0;
+	Plink=0; Plink(3)=1;
+	bool conv=false;
+	NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
+	for(unsigned int i=0; i<NumHeadJoints; i++)
+		setJointValue(i,headkin.get_q(2+i));
+	return conv;
 }
 
 int HeadPointerMC::updateOutputs() {
@@ -52,126 +72,51 @@
 	if(tmp) {
 		dirty=false;
 		for(unsigned int i=0; i<NumHeadJoints; i++) {
-			float value;
-			if(headModes[i]!=BodyRelative) {
-				value=convToBodyRelative((RobotInfo::TPROffset_t)i,headValues[i],headModes[i]);
-				dirty=true;
-			} else
-				value=headValues[i];
-			if(maxSpeed[i]<=0)
-				headJoints[i].value=value;
-			if(value==headJoints[i].value) {
-				motman->setOutput(this,i+HeadOffset,headJoints[i]);
+      if(maxSpeed[i]<=0) {
+				headCmds[i].value=headTargets[i];
+				motman->setOutput(this,i+HeadOffset,headCmds[i]);
 			} else { // we may be trying to exceeded maxSpeed
 				unsigned int f=0;
-				while(value>headJoints[i].value+maxSpeed[i] && f<NumFrames) {
-					headJoints[i].value+=maxSpeed[i];
-					motman->setOutput(this,i+HeadOffset,headJoints[i],f);
+				while(headTargets[i]>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
+					headCmds[i].value+=maxSpeed[i];
+					motman->setOutput(this,i+HeadOffset,headCmds[i],f);
 					f++;
 				}
-				while(value<headJoints[i].value-maxSpeed[i] && f<NumFrames) {
-					headJoints[i].value-=maxSpeed[i];
-					motman->setOutput(this,i+HeadOffset,headJoints[i],f);
+				while(headTargets[i]<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
+					headCmds[i].value-=maxSpeed[i];
+					motman->setOutput(this,i+HeadOffset,headCmds[i],f);
 					f++;
 				}
 				if(f<NumFrames) { //we reached target value, fill in rest of frames
-					headJoints[i].value=value;
+					headCmds[i].value=headTargets[i];
 					for(;f<NumFrames;f++)
-						motman->setOutput(this,i+HeadOffset,headJoints[i],f);
+						motman->setOutput(this,i+HeadOffset,headCmds[i],f);
 				} else // we didn't reach target value, still dirty
 					dirty=true;
 			}
 		}
-	}
-	return tmp;
-}
-
-const OutputCmd& HeadPointerMC::getOutputCmd(unsigned int i) {
-	i-=HeadOffset;
-	if(i<NumHeadJoints && getActive())
-		return headJoints[i];
-	else
-		return OutputCmd::unused;
-}
-
-/*! @todo this is perhaps a bit amateurish - could be more accurate */
-double HeadPointerMC::convToBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const {
-	switch(mode) {
-	default:
-		ASSERT(false,"Passed bad mode "<<mode);
-	case BodyRelative:
-		return v;
-	case GravityRelative: {
-		double bacc=state->sensors[BAccelOffset];
-		double lacc=state->sensors[LAccelOffset];
-		double dacc=state->sensors[DAccelOffset];
-		switch(i) {
-		case TiltOffset:
-			return v+atan2(bacc,sqrt(dacc*dacc+lacc*lacc));
-		case PanOffset:
-			return v;
-		case RollOffset: //==NodOffset
-			if(state->robotDesign&WorldState::ERS7Mask) {
-				float pans=sin(state->outputs[HeadOffset+PanOffset]);
-				float panc=cos(state->outputs[HeadOffset+PanOffset]);
-				float ans=v;
-				ans+=atan2(bacc*panc-lacc*pans,sqrt(dacc*dacc+lacc*lacc*panc*panc+bacc*bacc*pans*pans));
-				ans-=panc*state->outputs[HeadOffset+TiltOffset];
-				return ans;
-			} else
-				return v+atan2(-lacc,sqrt(dacc*dacc+bacc*bacc));
-		default:
-			ASSERT(false,"Passed bad offset "<<i<<" (use RobotInfo::TPROffset_t!)");
-			return v;
+		if(!dirty && !targetReached) {
+			postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
+			targetReached=true;
 		}
 	}
-	}
+	return tmp;
 }
 
-/*! @todo this is perhaps a bit amateurish - could be more accurate */
-double HeadPointerMC::convFromBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const {
-	switch(mode) {
-	default:
-		ASSERT(false,"Passed bad mode "<<mode);
-	case BodyRelative:
-		return v;
-	case GravityRelative: {
-		double bacc=state->sensors[BAccelOffset];
-		double lacc=state->sensors[LAccelOffset];
-		double dacc=state->sensors[DAccelOffset];
-		switch(i) {
-		case TiltOffset:
-			return v-atan2(bacc,sqrt(dacc*dacc+lacc*lacc));
-		case PanOffset:
-			return v;
-		case RollOffset: //==NodOffset
-			if(state->robotDesign&WorldState::ERS7Mask) {
-				float pans=sin(state->outputs[HeadOffset+PanOffset]);
-				float panc=cos(state->outputs[HeadOffset+PanOffset]);
-				float ans=v;
-				ans-=atan2(bacc*panc-lacc*pans,sqrt(dacc*dacc+lacc*lacc*panc*panc+bacc*bacc*pans*pans));
-				ans+=panc*state->outputs[HeadOffset+TiltOffset];
-				return ans;
-			} else
-				return v-atan2(-lacc,sqrt(dacc*dacc+bacc*bacc));
-		default:
-			ASSERT(false,"Passed bad offset "<<i<<" (use RobotInfo::TPROffset_t!)");
-			return v;
-		}
-	}
-	}
+void HeadPointerMC::markDirty() {
+	dirty=true;
+	targetReached=false;
 }
 
-
 /*! @file
  * @brief Implements HeadPointerMC, a class for various ways to control where the head is looking
  * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.14 $
  * $State: Exp $
- * $Date: 2004/01/19 07:56:16 $
+ * $Date: 2004/10/14 21:59:23 $
  */
 
 
Index: Motion/HeadPointerMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/HeadPointerMC.h,v
retrieving revision 1.7
retrieving revision 1.14
diff -u -d -r1.7 -r1.14
--- Motion/HeadPointerMC.h	7 Sep 2003 22:14:01 -0000	1.7
+++ Motion/HeadPointerMC.h	14 Oct 2004 23:02:53 -0000	1.14
@@ -5,66 +5,115 @@
 #include "MotionCommand.h"
 #include "OutputCmd.h"
 #include "Shared/RobotInfo.h"
+#include "roboop/robot.h"
 
 //! This class gives some quick and easy functions to point the head at things
 class HeadPointerMC : public MotionCommand {
- public:
-	//! constructor, defaults to active, BodyRelative, all joints at 0
+public:
+	//! Constructor, defaults to all joints to current value in ::state
 	HeadPointerMC();
-	//! destructor
+	
+	//! Destructor
 	virtual ~HeadPointerMC() {}
-
-	//! Various modes the head can be in.  In the future may want to add ability to explicitly track an object or point in the world model
-	enum CoordFrame_t {
-		BodyRelative,    //!<holds neck at a specified position, like a PostureEngine, but neck specific
-		GravityRelative  //!<uses accelerometers to keep a level head, doesn't apply for pan joint, but in future could use localization for pan
-	};
-
-	       void   setWeight(double w);                               //!< sets the weight values for all the neck joints
-	inline void   setWeight(RobotInfo::TPROffset_t i, double weight) { dirty=true; headJoints[i].weight=weight; } //!< set a specific head joint weight, pass one of RobotInfo::TPROffset_t, not a full offset!
-	inline void   setActive(bool a)                                  { active=a; } //!< sets #active flag, see isDirty()
-	inline bool   getActive() const                                  { return active; } //!< returns #active flag, see isDirty()
-
-	       void   noMaxSpeed()                                       { for(unsigned int i=0; i<NumHeadJoints; i++) maxSpeed[i]=0; } //!< sets #maxSpeed to 0 (no maximum)
-	       void   defaultMaxSpeed();                                 //!< restores #maxSpeed to default settings from Config::Motion_Config
-	       void   setMaxSpeed(TPROffset_t i, float x)                { maxSpeed[i]=x*FrameTime/1000; } //!< sets #maxSpeed, pass it rad/sec
-	       float  getMaxSpeed(TPROffset_t i)                         { return maxSpeed[i]*1000/FrameTime; } //!< returns #maxSpeed in rad/sec
-
-	//! converts a value @a v in @a srcmode to a value in @a tgtmode that would leave the joint angle for joint @a i constant (you probably won't need to call this directly)
-	inline double convert(RobotInfo::TPROffset_t i, double v, CoordFrame_t srcmode, CoordFrame_t tgtmode) const {
-		return (srcmode==tgtmode)?v:convFromBodyRelative(i,convToBodyRelative(i, v, srcmode),tgtmode);
-	}
-
-	//!Note that none of these are @c virtual, so you don't have to checkout to use them, you @e should be able to use MotionManager::peekMotion()
+	
+	//!@name Speed Control
+	
+	//! Sets #maxSpeed to 0 (no maximum)
+	void noMaxSpeed() { for(unsigned int i=0; i<NumHeadJoints; i++) maxSpeed[i]=0; }
+	
+	//! Restores #maxSpeed to default settings from Config::Motion_Config
+	void defaultMaxSpeed();
+	
+	//! Sets #maxSpeed in rad/sec
+	/*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
+	 *  @param x maximum radians per second to move */
+	void setMaxSpeed(unsigned int i, float x) { maxSpeed[i]=x*FrameTime/1000; }
+	
+	//! Returns #maxSpeed in rad/sec
+	/*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
+	 *  @return the maximum speed of joint @a i in radians per second */
+	float getMaxSpeed(unsigned int i) { return maxSpeed[i]*1000/FrameTime; }
+	
+	//@}
+	
 	//!@name Joint Accessors
-	       void   setJoints(double tilt, double pan, double roll);	                      //!< Directly sets the neck values, uses current mode
-	       void   setMode(CoordFrame_t m, bool convert=true);                                   //!< sets all the joints to the given mode, will convert the values to the new mode if @a convert is true
-	       void   setJointMode(RobotInfo::TPROffset_t i, CoordFrame_t m, bool convert=true);    //!< set a specific head joint's mode, will convert from previous mode's value to next mode's value if convert is true.  Pass one of RobotInfo::TPROffset_t, not a full offset!
-	inline void   setJointValue(RobotInfo::TPROffset_t i, double value)                   { dirty=true; headValues[i]=value;} //!< set a specific head joint's value (for whatever mode it's in), pass one of RobotInfo::TPROffset_t, not a full offset!
-	inline void   setJointValueAndMode(RobotInfo::TPROffset_t i, double value, CoordFrame_t m)  { dirty=true; headValues[i]=value; headModes[i]=m; } //!< set a specific head joint, pass one of RobotInfo::TPROffset_t, not a full offset!
-	inline void   setJointValueFromMode(RobotInfo::TPROffset_t i, double value, CoordFrame_t m) { dirty=true; headValues[i]=convert(i,value,m,headModes[i]); } //!< set a specific head joint auto converting @a value from mode @a m to the current mode, pass one of RobotInfo::TPROffset_t, not a full offset!
-	inline CoordFrame_t getJointMode(RobotInfo::TPROffset_t i) const                            { return headModes[i]; } //!< returns the current mode for joint @a i (use RobotInfo::TPROffset_t, not global offset)
-	inline double getJointValue(RobotInfo::TPROffset_t i) const                           { return headValues[i]; } //!< returns the current value (relative to the current mode) of joint @a i, use getOutputCmd() if you want to know the actual @b target joint value (to get the actual current joint position, look in WorldState
+	
+	//! Sets the weight values for all the neck joints
+	void setWeight(float w);
+	
+	//! Directly sets the neck values (all values in radians)
+	/*! @param j1 value for first neck joint (tilt on all ERS models)
+	 *  @param j2 value for second neck joint (pan on all ERS models)
+	 *  @param j3 value for third neck joint (nod on ERS-7, roll on ERS-2xx) */
+	void setJoints(float j1, float j2, float j3);
+	
+	//! Directly set a single neck joint value
+	/*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
+	 *  @param value the value to be assigned to join @a i, in radians */
+	void setJointValue(unsigned int i, float value) { headTargets[i]=clipAngularRange(HeadOffset+i,value); 	markDirty(); }
+	
+	//! Returns the target value of joint @a i.  Use this if you want to know the current @b commanded joint value; To get the current joint @b position, look in WorldState::outputs
+	/*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t) */
+	float getJointValue(unsigned int i) const { return headTargets[i]; }
+	
+	//! Centers the camera on a point in space, attempting to keep the camera as far away from the point as possible
+	/*! @param x location in millimeters
+	 *  @param y location in millimeters
+	 *  @param z location in millimeters */
+	bool lookAtPoint(float x, float y, float z);
+	
+	//! Centers the camera on a point in space, attempting to move the camera @a d millimeters away from the point
+	/*! @param x location in millimeters
+	 *  @param y location in millimeters
+	 *  @param z location in millimeters
+	 *  @param d target distance from point in millimeters */
+	bool lookAtPoint(float x, float y, float z, float d);
+	
+	//! Points the camera in a given direction
+	/*! @param x component of the direction vector
+	 *  @param y component of the direction vector
+	 *  @param z component of the direction vector */
+	bool lookInDirection(float x, float y, float z);
+	
 	//@}
-
+	
+	
 	//!@name Inherited:
-	virtual int              updateOutputs(  );             //!< Updates where the head is looking
-	virtual const OutputCmd& getOutputCmd(unsigned int i);  //!< returns one of the #headJoints entries or ::unusedJoint if not a head joint
-	virtual int              isDirty()                      { return (dirty && active)?1:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
-	virtual int              isAlive()                      { return true; }
+	virtual int updateOutputs(); //!< Updates where the head is looking
+	virtual int isDirty() { return (dirty || !targetReached)?3:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
+	virtual int isAlive() { return true; } //!< always true, doesn't autoprune (yet)
+	virtual void DoStart() { MotionCommand::DoStart(); markDirty(); } //!< marks this as dirty each time it is added
 	//@}
 
  protected:
-	double convToBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const;   //!< converts to a body relative measurement for joint @a i
-	double convFromBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const; //!< converts from a body relative measurement for joint @a i
-
-	bool dirty;                         //!< true if a change has been made since last call to updateJointCmds()
-	bool active;                        //!< set by accessor functions, defaults to true
-	OutputCmd headJoints[NumHeadJoints]; //!< stores the last values we sent from updateOutputs
-	float headValues[NumHeadJoints];   //!< stores the target value of each joint, relative to #headModes
-	CoordFrame_t headModes[NumHeadJoints];    //!< stores the current mode of each joint, for instance so tilt can be GravityRelative while pan is static
+	//! puts x in the range (-pi,pi)
+	static float normalizeAngle(float x) { return x-rint(x/(2*M_PI))*(2*M_PI); }
 	
-	float maxSpeed[NumHeadJoints];   //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
+	//! if @a x is outside of the range of joint @a i, it is set to either the min or the max, whichever is closer
+	static float clipAngularRange(unsigned int i, float x) {
+		float min=outputRanges[i][MinRange];
+		float max=outputRanges[i][MaxRange];
+		if(x<min || x>max) {
+			float mn_dist=fabs(normalizeAngle(min-x));
+			float mx_dist=fabs(normalizeAngle(max-x));
+			if(mn_dist<mx_dist)
+				return min;
+			else
+				return max;
+		} else
+			return x;
+	}
+	//! if targetReached, reassigns headCmds from ::state, then sets dirty to true and targetReached to false
+	/*! should be called each time a joint value gets modified in case
+	 *  the head isn't where it's supposed to be, it won't jerk around */
+	void markDirty();
+
+	bool dirty;                          //!< true if a change has been made since last call to updateJointCmds()
+	bool targetReached;                  //!< false if the head is still moving towards its target
+  float headTargets[NumHeadJoints];    //!< stores the target value of each joint
+	OutputCmd headCmds[NumHeadJoints];   //!< stores the last values we sent from updateOutputs
+	float maxSpeed[NumHeadJoints];       //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
+	ROBOOP::Robot headkin;               //!< provides kinematics computations
 };
 
 /*! @file
@@ -73,9 +122,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.7 $
- * $State: Rel $
- * $Date: 2003/09/07 22:14:01 $
+ * $Revision: 1.14 $
+ * $State: Exp $
+ * $Date: 2004/10/14 23:02:53 $
  */
 
 #endif
Index: Motion/Kinematics.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/Kinematics.cc,v
retrieving revision 1.5
retrieving revision 1.18
diff -u -d -r1.5 -r1.18
--- Motion/Kinematics.cc	26 Feb 2004 01:02:49 -0000	1.5
+++ Motion/Kinematics.cc	17 Oct 2004 01:16:10 -0000	1.18
@@ -1,461 +1,414 @@
-//This class is ported from Carnegie Mellon's 2001 Robosoccer entry, and falls under their license:
-/*=========================================================================
-    CMPack'02 Source Code Release for OPEN-R SDK v1.0
-    Copyright (C) 2002 Multirobot Lab [Project Head: Manuela Veloso]
-    School of Computer Science, Carnegie Mellon University
-  -------------------------------------------------------------------------
-    This software is distributed under the GNU General Public License,
-    version 2.  If you do not have a copy of this licence, visit
-    www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
-    Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
-    in the hope that it will be useful, but WITHOUT ANY WARRANTY,
-    including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  -------------------------------------------------------------------------
-    Additionally licensed to Sony Corporation under the following terms:
-
-    This software is provided by the copyright holders AS IS and any
-    express or implied warranties, including, but not limited to, the
-    implied warranties of merchantability and fitness for a particular
-    purpose are disclaimed.  In no event shall authors be liable for
-    any direct, indirect, incidental, special, exemplary, or consequential
-    damages (including, but not limited to, procurement of substitute
-    goods or services; loss of use, data, or profits; or business
-    interruption) however caused and on any theory of liability, whether
-    in contract, strict liability, or tort (including negligence or
-    otherwise) arising in any way out of the use of this software, even if
-    advised of the possibility of such damage.
-  =========================================================================
-*/
-
-#ifdef PLATFORM_LINUX
-#include <stdlib.h>
-#include <stdio.h>
-#endif
-
-#include <math.h>
-
 #include "Kinematics.h"
+#include "Shared/Config.h"
+#include "roboop/robot.h"
+#include "roboop/config.h"
+#include "Shared/WorldState.h"
+#include <sstream>
 
-// #define DEBUG
-
-// ERS-210 Leg Parameters
-const vector3d f_body_to_shoulder       ( 59.50, 59.20,   0.00);
-const vector3d f_leg_shoulder_to_knee   ( 12.80,  0.50, -64.00);
-const vector3d f_leg_knee_to_ball       (-18.00,  0.00, -67.23);
-
-const vector3d h_body_to_shoulder       (-59.50, 59.20,   0.00);
-const vector3d h_leg_shoulder_to_knee   (-12.80,  0.50, -64.00);
-const vector3d h_leg_knee_to_ball       ( 18.00,  0.00, -74.87);
+using namespace std;
 
-/*
-  18 : measured
-  67.23 = sqrt(69.6^2 - 18^2)
-  74.87 = sqrt(77^2 - 18^2)
-  0.2616 = asin(18 / 69.6)
-  0.2316 = asin(18 / 77)
-*/
+Kinematics * kine = NULL;
+ROBOOP::Config * Kinematics::roconfig = NULL;
+Kinematics::InterestPointMap * Kinematics::ips = NULL;
 
-/* ERS-110
-const vector3d f_body_to_shoulder       ( 44.85, 26.50,   0.00);
-const vector3d f_leg_shoulder_to_knee   ( 13.00,  5.50, -61.00);
-const vector3d f_leg_knee_to_ball       ( -9.50,  1.06, -58.00); // ??
+void
+Kinematics::init() {
+	unsigned int nchains=::config->motion.kinematic_chains.size();
+	if(nchains==0) {
+		serr->printf("ERROR Kinematics::init(): no kinematic chains were selected\n");
+		return;
+	}
+	jointMaps[BaseFrameOffset]=JointMap(0,0);
+	chains.resize(nchains);
+	chainMaps.resize(nchains);
+	if(roconfig==NULL)
+		roconfig=new ROBOOP::Config(::config->motion.makePath(::config->motion.kinematics),true);
+	for(unsigned int i=0; i<nchains; i++) {
+		string section=::config->motion.kinematic_chains[i];
+		chains[i]=new ROBOOP::Robot(*roconfig,section);
+		int dof=0;
+		if(roconfig->select_int(section,"dof",dof)!=0) {
+			serr->printf("ERROR Kinematics::init(): unable to find 'dof' in chain %d (%s)\n",i,section.c_str());
+			return;
+		}
+		chainMaps[i].resize(dof+1);
+		for(int l=0; l<=dof; l++)
+			chainMaps[i][l]=-1U;
+		for(int l=1; l<=dof; l++) {
+			ostringstream ostr;
+			ostr << section << "_LINK" << l;
+			string link = ostr.str();
+			if(roconfig->parameter_exists(link,"tekkotsu_output")) {
+				int tkout=-1U;
+				roconfig->select_int(link,"tekkotsu_output",tkout);
+				if((unsigned int)tkout>=NumOutputs) {
+					serr->printf("WARNING Kinematics::init(): invalid tekkotsu_output %d on chain %d (%s), link %d (%s)\n",tkout,i,section.c_str(),l,link.c_str());
+				} else {
+					jointMaps[tkout]=JointMap(i,l);
+					chainMaps[i][l]=tkout;
+				}
+			}
+			if(roconfig->parameter_exists(link,"tekkotsu_frame")) {
+				int tkout=-1U;
+				roconfig->select_int(link,"tekkotsu_frame",tkout);
+				tkout+=NumOutputs;
+				if((unsigned int)tkout>=NumReferenceFrames)
+					serr->printf("WARNING Kinematics::init(): invalid tekkotsu_frame %d on chain %d (%s), link %d (%s)\n",tkout,i,section.c_str(),l,link.c_str());
+				else
+					jointMaps[tkout]=JointMap(i,l);
+			}
+		}
+	}
 
-const vector3d h_body_to_shoulder       (-44.85, 26.50,   0.00);
-const vector3d h_leg_shoulder_to_knee   (-13.00,  5.50, -61.00);
-const vector3d h_leg_knee_to_ball       ( 19.00,  1.06, -69.00); // ??
-*/
+	if(ips==NULL) {
+		int numIP=0;
+		roconfig->select_int("InterestPoints","Length",numIP);
+		ips=new InterestPointMap(numIP);
+		pair<string,InterestPoint> ip;
+		string chain;
+		for(int i=1; i<=numIP; i++) {
+			char section[100];
+			snprintf(section,100,"InterestPoint%d",i);
+			roconfig->select_float(section,"x",ip.second.x);
+			roconfig->select_float(section,"y",ip.second.y);
+			roconfig->select_float(section,"z",ip.second.z);
+			roconfig->select_string(section,"chain",chain);
+			roconfig->select_int(section,"link",ip.second.link);
+			roconfig->select_string(section,"name",ip.first);
+			for(ip.second.chain=0; ip.second.chain<(::config->motion.kinematic_chains.size()); ip.second.chain++)
+				if(::config->motion.kinematic_chains[ip.second.chain]==chain)
+					break;
+			if(ip.second.chain==::config->motion.kinematic_chains.size())
+				serr->printf("WARNING: Chain %s is not recognized for interest point %d\n",chain.c_str(),i);
+			else
+				ips->insert(ip);
+		}
+	}
 
-#ifdef PLATFORM_LINUX
-void print(double *angles,vector3d pos)
-{
-  printf("A(%7.4f,%7.4f,%7.4f) P(%7.2f,%7.2f,%7.2f)\n",
-	 angles[0],angles[1],angles[2],
-	 pos.x,pos.y,pos.z);
+	/*cout << "Joint Maps" << endl;
+	for(unsigned int i=0; i<NumOutputs; i++)
+		cout << outputNames[i] << ": " << jointMaps[i].chain << ' ' << jointMaps[i].link << endl;
+	for(unsigned int i=NumOutputs; i<NumReferenceFrames; i++)
+		cout << i << ": " << jointMaps[i].chain << ' ' << jointMaps[i].link << endl;
+	cout << "Chain Maps" << endl;
+	for(unsigned int i=0; i<chains.size(); i++)
+		for(unsigned int j=1; j<chainMaps[i].size(); j++)
+		cout << "chainMaps["<<i<<"]["<<j<<"] == " << chainMaps[i][j] << endl;*/
 }
-#endif
-
-
-const vector3d f_upper = f_leg_shoulder_to_knee;
-const vector3d f_lower = f_leg_knee_to_ball;
-const vector3d h_upper = h_leg_shoulder_to_knee;
-const vector3d h_lower = h_leg_knee_to_ball;
-
-//==== Globals ====//
-#ifdef PLATFORM_LINUX
-int g_leg;
-vector3d g_target;
-#endif
-
-static int errors;
 
-void KinClearErrors()
-{
-  errors = 0;
+NEWMAT::ReturnMatrix
+Kinematics::frameToBase(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	update(c,l);
+	return chains[c]->convertFrame(l,0);
 }
 
-int KinGetErrors()
-{
-  return(errors);
+NEWMAT::ReturnMatrix
+Kinematics::linkToBase(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	update(c,l);
+	return chains[c]->convertLink(l,0);
 }
 
-double GetTrigAngle(double a,double b,double d,double mn,double mx,bool add)
-// Analytic solution to a*sin(x) + b*cos(x) = d
-{
-  double theta;
-  double t,f,c;
-  int err;
-
-  f = d / sqrt(a*a + b*b);
-  err = 0;
-
-  if(fabs(f) > 1.0){
-#ifdef PLATFORM_LINUX
-    /*
-    printf("Out of range (distance=%g) leg=%d target=(%g,%g,%g)\n",f,
-           g_leg,g_target.x,g_target.y,g_target.z);
-    */
-#endif
-    f = (f > 0.0)? 1.0 : -1.0;
-    err = 1;
-  }
-
-  t = atan2(a,b);
-  c = acos(f);
-
-  theta = add? (t + c) : (t - c);
-
-  if(theta < mn){
-#ifdef PLATFORM_LINUX
-    /*
-    printf("Out of range (angle to small) leg=%d target=(%g,%g,%g)\n",
-           g_leg,g_target.x,g_target.y,g_target.z);
-    */
-#endif
-    errors++;
-    return(mn);
-  }else if(theta > mx){
-#ifdef PLATFORM_LINUX
-    /*
-    printf("Out of range (angle to large) leg=%d target=(%g,%g,%g)\n",
-           g_leg,g_target.x,g_target.y,g_target.z);
-    */
-#endif
-    errors++;
-    return(mx);
-  }else{
-    errors += err;
-    return(theta);
-  }
+NEWMAT::ReturnMatrix
+Kinematics::baseToFrame(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	update(c,l);
+	return chains[c]->convertFrame(0,l);
 }
 
-/*
-Angle Limits:
-           ===Software====  ==Mechanical===
-  Rotator  [-117.0, 117.0]  [-120.0, 120.0]
-  Shoulder [ -11.0,  97.0]  [ -14.0, 100.0]
-  Knee     [ -27.0, 147.0]  [ -30.0, 150.0]
-*/
-
-const double rotator_min  = RAD(-117.0);
-const double rotator_max  = RAD( 117.0);
-const double shoulder_min = RAD( -11.0);
-const double shoulder_max = RAD(  97.0);
-const double knee_max     = RAD( 147.0);
-const double knee_min     = RAD( -27.0);
-
-const double rotator_kmin  = RAD(-90.0);
-const double rotator_kmax  = RAD( 90.0);
-const double shoulder_kmin = shoulder_min;
-const double shoulder_kmax = RAD( 90.0);
-const double knee_kmax     = knee_max;
-const double f_knee_kmin   = 0.2616;
-const double h_knee_kmin   = 0.2316;
-
-const double tail_min = RAD(-22);
-const double tail_max = RAD( 22);
-
-const double head_tilt_min = RAD(-88.5);
-const double head_tilt_max = RAD( 43.0);
-const double head_pan_min  = RAD(-89.6);
-const double head_pan_max  = RAD( 89.6);
-const double head_roll_min = RAD(-29.0);
-const double head_roll_max = RAD( 29.0);
-
-
-void GetLegAngles(double *angles,vector3d target,int leg)
-{
-  vector3d targ,pos;
-  double knee,shoulder,rotator;
-  double a,b,d,dist;
-  bool front = leg < 2;
-
-#ifdef PLATFORM_LINUX
-  g_leg    = leg;
-  g_target = target;
-  // printf("GLA: target=(%g,%g,%g)\n",target.x,target.y,target.z);
-#endif
-
-  knee = shoulder = rotator = 0.0;
-
-  if(leg % 2) target.y = -target.y;
-
-  if(front){
-    targ = target - f_body_to_shoulder;
-    dist = targ.sqlength();
-
-    // Calculate knee angle
-    a = -2*(f_upper.x*f_lower.z - f_upper.z*f_lower.x);
-    b =  2*(f_upper.x*f_lower.x + f_upper.z*f_lower.z);
-    d = (dist - f_upper.sqlength() - f_lower.sqlength() - 2*f_upper.y*f_lower.y);
-    knee = GetTrigAngle(a,b,d,f_knee_kmin,knee_kmax,true);
-
-    // Calculate shoulder angle
-    pos = f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-knee);
-    shoulder = GetTrigAngle(-pos.z,pos.y,targ.y,shoulder_kmin,shoulder_kmax,false);
-
-    // Calculate rotator angle
-    // pos = pos.rotate_x(shoulder);
-    pos.z = sin(shoulder)*pos.y + cos(shoulder)*pos.z;
-    rotator = GetTrigAngle(-pos.z,pos.x,targ.x,rotator_min,rotator_max,target.z > 0.0);
-
-#ifdef DEBUG
-    // Test
-		//    pos = (f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-knee))
-		//           .rotate_x(shoulder).rotate_y(-rotator);
-		//    printf("D(%f,%f,%f)\n",targ.x - pos.x,targ.y - pos.y,targ.z - pos.z);
-#endif
-  }else{
-    targ = target - h_body_to_shoulder;
-    dist = targ.sqlength();
-
-    // Calculate knee angle
-    a = 2*(h_upper.x*h_lower.z - h_upper.z*h_lower.x);
-    b = 2*(h_upper.x*h_lower.x + h_upper.z*h_lower.z);
-    d = (dist - h_upper.sqlength() - h_lower.sqlength() - 2*h_upper.y*h_lower.y);
-    knee = GetTrigAngle(a,b,d,h_knee_kmin,knee_kmax,true);
-
-    // Calculate shoulder angle
-    pos = h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y(knee);
-    shoulder = GetTrigAngle(-pos.z,pos.y,targ.y,shoulder_kmin,shoulder_kmax,false);
-
-    // Calculate rotator angle
-    pos.z = sin(shoulder)*pos.y + cos(shoulder)*pos.z;
-    rotator = GetTrigAngle(-pos.z,-pos.x,-targ.x,rotator_min,rotator_max,target.z > 0.0);
-
-    /*
-    if(fabs(theta - rotator) > 0.01){
-      printf("ERROR(%f - %f = %f)\n",theta,rotator,theta - rotator);
-    }
-    */
-
-#ifdef DEBUG
-    // Test
-		//    pos = (h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y(angles[2]))
-		//           .rotate_x(angles[1]).rotate_y(angles[0]);
-		//    printf("D(%f,%f,%f)\n",targ.x - pos.x,targ.y - pos.y,targ.z - pos.z);
-#endif
-  }
-
-  angles[0] = rotator;
-  angles[1] = shoulder;
-  angles[2] = knee;
+NEWMAT::ReturnMatrix
+Kinematics::baseToLink(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	update(c,l);
+	return chains[c]->convertLink(0,l);
 }
 
-void GetLegAngles(double *angles,vector3d target[4],
-                  double body_angle,double body_height)
-{
-  vector3d p;
-  int i;
+NEWMAT::ReturnMatrix
+Kinematics::frameToFrame(unsigned int ij, unsigned int oj) {
+	unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
+	if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	if(ci==co) {
+		update(ci,li>lo?li:lo);
+		return chains[ci]->convertFrame(li,lo);
+	} else if(li==0) {
+		update(co,lo);
+		return chains[co]->convertFrame(0,lo);
+	} else if(lo==0) {
+		update(ci,li);
+		return chains[ci]->convertFrame(li,0);
+	} else {
+		update(ci,li);
+		update(co,lo);
+		NEWMAT::Matrix ans=chains[co]->convertFrame(0,lo)*chains[ci]->convertFrame(li,0);
+		ans.Release(); return ans;
+	}
+}
 
-  for(i=0; i<4; i++){
-    p = target[i];
-    p.z -= body_height;
-    p = p.rotate_y(-body_angle);
-    GetLegAngles(angles + 3*i,p,i);
-  }
+NEWMAT::ReturnMatrix
+Kinematics::frameToLink(unsigned int ij, unsigned int oj) {
+	unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
+	if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	if(ci==co) {
+		update(ci,li>lo?li:lo);
+		return chains[ci]->convertFrameToLink(li,lo);
+	} else if(li==0) {
+		update(co,lo);
+		return chains[co]->convertFrameToLink(0,lo);
+	} else if(lo==0) {
+		update(ci,li);
+		return chains[ci]->convertFrameToLink(li,0);
+	} else {
+		update(ci,li);
+		update(co,lo);
+		NEWMAT::Matrix ans=chains[co]->convertLink(0,lo)*chains[ci]->convertFrame(li,0);
+		ans.Release(); return ans;
+	}
 }
 
-void GetLegAngles(double *angles,vector3d target[4],BodyPosition &bp)
-{
-  vector3d p;
-  int i;
+NEWMAT::ReturnMatrix
+Kinematics::linkToFrame(unsigned int ij, unsigned int oj) {
+	unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
+	if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	if(ci==co) {
+		update(ci,li>lo?li:lo);
+		return chains[ci]->convertLinkToFrame(li,lo);
+	} else if(li==0) {
+		update(co,lo);
+		return chains[co]->convertLinkToFrame(0,lo);
+	} else if(lo==0) {
+		update(ci,li);
+		return chains[ci]->convertLinkToFrame(li,0);
+	} else {
+		update(ci,li);
+		update(co,lo);
+		NEWMAT::Matrix ans=chains[co]->convertFrame(0,lo)*chains[ci]->convertLink(li,0);
+		ans.Release(); return ans;
+	}
+}
 
-  for(i=0; i<4; i++){
-    p = (target[i] - bp.loc).rotate_z(bp.angle.z).rotate_y(-bp.angle.y);
-    GetLegAngles(angles + 3*i,p,i);
-  }
+NEWMAT::ReturnMatrix
+Kinematics::linkToLink(unsigned int ij, unsigned int oj) {
+	unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
+	if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	if(ci==co) {
+		update(ci,li>lo?li:lo);
+		return chains[ci]->convertLink(li,lo);
+	} else if(li==0) {
+		update(co,lo);
+		return chains[co]->convertLink(0,lo);
+	} else if(lo==0) {
+		update(ci,li);
+		return chains[ci]->convertLink(li,0);
+	} else {
+		update(ci,li);
+		update(co,lo);
+		NEWMAT::Matrix ans=chains[co]->convertLink(0,lo)*chains[ci]->convertLink(li,0);
+		ans.Release(); return ans;
+	}
 }
 
-void GetLegAngles(double *angles,vector3d target,BodyPosition &bp,int leg)
-{
-  vector3d p;
+void
+Kinematics::getInterestPoint(const std::string& name, unsigned int& j, NEWMAT::Matrix& ip) {
+	unsigned int c=-1U,l=-1U;
+	getInterestPoint(name,c,l,ip);
+	j=chainMaps[c][l];
+}
 
-  p = (target - bp.loc).rotate_z(bp.angle.z).rotate_y(-bp.angle.y);
-  GetLegAngles(angles,p,leg);
+void
+Kinematics::getInterestPoint(const std::string& name, unsigned int& c, unsigned int& l, NEWMAT::Matrix& ip) {
+	InterestPointMap::iterator it=ips->find(name);
+	ip=NEWMAT::ColumnVector(4);
+	if(it==ips->end()) {
+		serr->printf("ERROR: '%s' is not a recognized interest point\n",name.c_str());
+		ip=0;
+		c=l=-1U;
+	}
+	c=(*it).second.chain;
+	l=(*it).second.link;
+	ip=pack((*it).second.x,(*it).second.y,(*it).second.z);
+	//cout << ci << ' ' << li << ' ' << co << ' ' << lo << endl;
 }
 
+NEWMAT::ReturnMatrix
+Kinematics::getFrameInterestPoint(unsigned int frame, const std::string& name) {
+	NEWMAT::ColumnVector ans(4);
+	ans=0;
+	unsigned int co=-1U,lo=-1U;
+	if(!lookup(frame,co,lo)) {
+		ans.Release(); return ans;
+	}
+	for(unsigned int pos=0,len=0; pos<name.size(); pos+=len+1) {
+		len=name.find(',',pos);
+		if(len==string::npos)
+			len=name.size();
+		len-=pos;
+		unsigned int ci=-1U,li=-1U;
+		NEWMAT::ColumnVector ip;
+		getInterestPoint(name.substr(pos,len),ci,li,ip);
+		if(ci==-1U) {
+			ip.Release(); return ip;
+		}
+		if(ci==co) {
+			update(ci,li>lo?li:lo);
+			ans+=chains[ci]->convertLinkToFrame(li,lo)*ip;
+		} else if(li==0) {
+			update(co,lo);
+			ans+=chains[co]->convertLinkToFrame(0,lo)*ip;
+		} else if(lo==0) {
+			update(ci,li);
+			ans+=chains[ci]->convertLinkToFrame(li,0)*ip;
+		} else {
+			update(ci,li);
+			update(co,lo);
+			ans+=chains[co]->convertFrame(0,lo)*chains[ci]->convertLink(li,0)*ip;
+		}
+	}
+	ans/=ans(4); //not strictly necessary, but may save some people headaches
+	ans.Release(); return ans;
+}
 
-void GetLegPosition(vector3d& p, const double* ang, int leg)
-{
-	if(leg < 2){
-		p = f_body_to_shoulder +
-			(f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-ang[2]))
-			.rotate_x(ang[1]).rotate_y(-ang[0]);
-	}else{
-		p = h_body_to_shoulder +
-			(h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y( ang[2]))
-			.rotate_x(ang[1]).rotate_y( ang[0]);
+LegOrder_t
+Kinematics::findUnusedLeg(const NEWMAT::ColumnVector& down) {
+	float height[NumLegs]; //not actually the real height, but proportional to it, which is all we need
+	for(unsigned int i=0; i<NumLegs; i++) {
+		height[i]=NEWMAT::DotProduct(frameToBase(PawFrameOffset+i).SubMatrix(1,3,4,4),down.SubMatrix(1,3,1,1));
+		//cout << "height["<<i<<"]=="<<height[i]<<endl;
 	}
 	
-	if(leg % 2)
-		p.y = -p.y;
-}
-void GetLegPosition(vector3d& p, const double* ang, BodyPosition &bp,int leg)
-{
-	GetLegPosition(p,ang,leg);
-	p=p.rotate_y(bp.angle.y).rotate_z(-bp.angle.z)+bp.loc;
+	//Find the highest foot
+	unsigned int highleg=0;
+	for(unsigned int i=1; i<NumLegs; i++)
+		if(height[highleg]>height[i])
+			highleg=i;
+	//cout << "High: " << highleg << endl;
+	return static_cast<LegOrder_t>(highleg);
 }
 
-
-void GetBodyLocation(vector3d &ball,vector3d &toe,const double *ang,int leg)
-// project various parts of foot that could touch by given joint angles
-{
-  if(leg < 2){
-    ball = f_body_to_shoulder +
-           (f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-ang[2]))
-           .rotate_x(ang[1]).rotate_y(-ang[0]);
-  }else{
-    ball = h_body_to_shoulder +
-           (h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y( ang[2]))
-           .rotate_x(ang[1]).rotate_y( ang[0]);
-  }
-
-  // TODO: toes
-  toe = ball;
-
-  if(leg % 2){
-    ball.y = -ball.y;
-    toe.y = -toe.y;
-  }
+NEWMAT::ReturnMatrix
+Kinematics::calculateGroundPlane(const NEWMAT::ColumnVector& down) {
+	//Find the unused foot
+	unsigned int highleg=findUnusedLeg(down);
+	
+	//Fit a plane to the remaining 3 feet
+	NEWMAT::Matrix legs(3,3);
+	for(unsigned int i=0; i<highleg; i++)
+		legs.Column(i+1)=frameToBase(PawFrameOffset+i).SubMatrix(1,3,4,4);
+	for(unsigned int i=highleg+1; i<NumLegs; i++)
+		legs.Column(i)=frameToBase(PawFrameOffset+i).SubMatrix(1,3,4,4);
+	//cout << legs;
+	NEWMAT::ColumnVector ones(3); ones=1;
+	NEWMAT::ColumnVector p(4);
+	p.SubMatrix(1,3,1,1) = legs.t().i()*ones;
+	p(4)=1;
+	p.Release(); return p;
 }
 
-void GetHeadAngles(double *angles,vector3d target,
-                   double body_angle,double body_height)
+NEWMAT::ReturnMatrix
+Kinematics::projectToPlane(unsigned int j, const NEWMAT::ColumnVector& r_j,
+                           unsigned int b, const NEWMAT::ColumnVector& p_b,
+                           unsigned int f)
 {
-  double tilt,pan;
-
-  vector3d neck;
-  double height;
-
-#ifdef PLATFORM_APERIOS
-  //pprintf(TextOutputStream,"target (%g,%g,%g) body_angle %g body_height %g\n",
-  //        target.x,target.y,target.z,
-  //        body_angle,body_height);
-#endif
-
-  // translate target so it is relative to base of neck
-  neck = body_to_neck.rotate_y(body_angle);
-  height = body_height + neck.z;
-  target.z -= height;
-  
-  double target_xz_dist; // distance in robot's xz plane of target
-
-  target_xz_dist=hypot(target.x,target.z);
-
-  // assumes that camera is aligned with base of neck
-  // can only see if not too close to neck
-  if(target_xz_dist > neck_to_camera.z && target.length() > neck_to_camera.length()) {
-    double angle_base_target; // angle from base of neck to target xz
-    double angle_base_target_camera; // angle between base and camera from target xz
-    
-    angle_base_target = atan2(target.z,target.x);
-    angle_base_target_camera = asin(neck_to_camera.z/target_xz_dist);
-    
-    tilt = angle_base_target - angle_base_target_camera + body_angle;
-    tilt = bound(tilt,head_tilt_min,head_tilt_max);
-    
-    double camera_dist_to_target;
-    camera_dist_to_target = sqrt(target_xz_dist*target_xz_dist - 
-                                 neck_to_camera.z*neck_to_camera.z);
-    
-    pan = atan2(target.y,camera_dist_to_target);
-    pan = bound(pan,head_pan_min,head_pan_max);
+	/*! Mathematcal implementation:
+	 *  
+	 *  Need to convert @a p_b to @a p_j
+	 *  
+	 *  Once we have the transformation Tb_j from b to j, we need:\n
+	 *    T2=inv(Tb_j)'; T2(3,1:end-1)=-T2(3,1:end-1);\n
+	 *  but since we know a few things about the structure of T,
+	 *  we don't have to explicitly calculate that inverse. */
+	NEWMAT::Matrix T2=linkToLink(b,j);
+	//cout << "Transform b->j:\n"<<T2;
+	T2.SubMatrix(4,4,1,3)=T2.SubMatrix(1,3,4,4).t()*T2.SubMatrix(1,3,1,3);
+	T2.SubMatrix(1,3,4,4)=0;
+	//cout << "Transform plane b->j:\n"<<T2;
+	NEWMAT::ColumnVector p_j=T2*p_b;
+	//cout << "p_j:\n"<<p_j.t();
 
-#ifdef PLATFORM_APERIOS
-    //pprintf(TextOutputStream,"txzd %g abt %g abtc %g tilt %g pan %g\n",
-    //        target_xz_dist,angle_base_target,angle_base_target_camera,
-    //        tilt,pan);
-#endif
-  }
-  else {
-    tilt = pan = 0.0;
-  }
+	
+	/*! After we obtain @a p_j, we can find the point of intersection of
+	 *  @a r_j and @a p_j using:
+	 *  @f[ \frac{p_d}{p_{xyz} \cdot r}r @f]
+	 *  Where @f$p_{xyz}@f$ is the first three elemnts of @a p_j, and
+	 *  @f$p_d@f$ is the fourth (hopefully last) element of p_j.
+	 *
+	 *  Of course, if @f$p_{xyz} \cdot r@f$ is 0, then r and p are parallel
+	 *  (since @a p_j is the normal of the plane, so a line perpendicular to
+	 *  the normal is parallel to the plane), so we set the resulting
+	 *  homogenous coordinates accordingly to represent an interesection at
+	 *  infinity. */
 
-  angles[0] = tilt;
-  angles[1] = pan;
-  angles[2] = 0.0; // roll
+	float denom=0;
+	for(unsigned int i=1; i<=3; i++)
+		denom+=r_j(i)*p_j(i);
+	NEWMAT::ColumnVector intersect=r_j;
+	if(denom==0)
+		intersect(4)=0;
+	else {
+		float s=p_j(4)/denom;
+		for(unsigned int i=1; i<=3; i++)
+			intersect(i)*=s;
+		intersect(4)=1;
+	}
+	//cout << "Intersect_j:\n"<<intersect.t();
+	NEWMAT::Matrix ans=linkToLink(j,f)*intersect;
+	ans.Release(); return ans;
 }
 
-vector3d
-RunForwardModel(double *angles, double body_angle, double body_height, vector3d point) {
-  double tilt=0.0,pan=0.0,roll=0.0;
-
-  tilt = angles[0];
-  pan  = angles[1];
-  roll = angles[2];
-
-  point = point.rotate_x(roll);
-  point += neck_to_camera;
-  point = point.rotate_z(pan);
-  point = point.rotate_y(-tilt+body_angle);
-
-  vector3d neck;
-
-  neck = body_to_neck;
-  neck = neck.rotate_y(body_angle);
-  neck.z += body_height;
-
-  point.z += neck.z;
-
-  return point;
+void
+Kinematics::update(unsigned int c, unsigned int l) {
+	for(unsigned int j=1; j<=l; j++) {
+		unsigned int tkout=chainMaps[c][j];
+		if(tkout<NumOutputs)
+			chains[c]->set_q(state->outputs[tkout],j);
+	}
 }
 
-// calculates the pose of the camera
-// location  = location of camera in robot coordinates relative to point on ground under neck
-// direction = unit vector pointing in direction of camera
-// up        = unit vector pointing in direction of higher on image
-// right     = unit vector pointing in direction of more right on image
-void GetHeadPosition(vector3d &location, vector3d &direction, vector3d &up, vector3d &right,
-                     double *angles, double body_angle, double body_height)
-{
-  location = RunForwardModel(angles, body_angle, body_height, vector3d(0.0,0.0,0.0));
-
-  vector3d image_x,image_y,image_z;
-
-  image_x = RunForwardModel(angles, body_angle, body_height, vector3d(0.0,-1.0, 0.0));
-  image_y = RunForwardModel(angles, body_angle, body_height, vector3d(0.0, 0.0, 1.0));
-  image_z = RunForwardModel(angles, body_angle, body_height, vector3d(1.0, 0.0, 0.0));
-
-  direction = image_z - location;
-  direction = direction.norm();
-
-  up = image_y - location;
-  up = up.norm();
-
-  right = image_x - location;
-  right = right.norm();
-}
 
 /*! @file
- * @brief Functions to provide kinematics calculations
- * @author CMU RoboSoccer 2001-2002 (Creator)
- * 
- * @verbinclude CMPack_license.txt
+ * @brief 
+ * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.5 $
+ * $Revision: 1.18 $
  * $State: Exp $
- * $Date: 2004/02/26 01:02:49 $
+ * $Date: 2004/10/17 01:16:10 $
  */
 
Index: Motion/Kinematics.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/Kinematics.h,v
retrieving revision 1.8
retrieving revision 1.23
diff -u -d -r1.8 -r1.23
--- Motion/Kinematics.h	26 Feb 2004 01:02:49 -0000	1.8
+++ Motion/Kinematics.h	19 Oct 2004 17:06:31 -0000	1.23
@@ -1,120 +1,326 @@
 //-*-c++-*-
-//This class is ported from Carnegie Mellon's 2001 Robosoccer entry, and falls under their license:
-/*=========================================================================
-    CMPack'02 Source Code Release for OPEN-R SDK v1.0
-    Copyright (C) 2002 Multirobot Lab [Project Head: Manuela Veloso]
-    School of Computer Science, Carnegie Mellon University
-  -------------------------------------------------------------------------
-    This software is distributed under the GNU General Public License,
-    version 2.  If you do not have a copy of this licence, visit
-    www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
-    Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
-    in the hope that it will be useful, but WITHOUT ANY WARRANTY,
-    including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  -------------------------------------------------------------------------
-    Additionally licensed to Sony Corporation under the following terms:
+#ifndef INCLUDED_Kinematics_h_
+#define INCLUDED_Kinematics_h_
 
-    This software is provided by the copyright holders AS IS and any
-    express or implied warranties, including, but not limited to, the
-    implied warranties of merchantability and fitness for a particular
-    purpose are disclaimed.  In no event shall authors be liable for
-    any direct, indirect, incidental, special, exemplary, or consequential
-    damages (including, but not limited to, procurement of substitute
-    goods or services; loss of use, data, or profits; or business
-    interruption) however caused and on any theory of liability, whether
-    in contract, strict liability, or tort (including negligence or
-    otherwise) arising in any way out of the use of this software, even if
-    advised of the possibility of such damage.
-  =========================================================================
-*/
+#include "Shared/RobotInfo.h"
+#include "Wireless/Socket.h"
+#include "Shared/newmat/newmat.h"
+#include <string>
+#include <vector>
+#include <ext/hash_map>
 
-#ifndef __KINEMATICS_H__
-#define __KINEMATICS_H__
+namespace ROBOOP {
+	class Robot;
+	class Config;
+}
 
-#include "Geometry.h"
-#include "Shared/Util.h"
+//! Provides access to the mathematical functionality of the ROBOOP package using Tekkotsu data structures
+/*! 
+ *  You should read the <a
+ *  href="http://www.tekkotsu.org/Kinematics.html">Kinematics
+ *  tutorial</a> to get a general understanding of the math involved
+ *  and diagrams for usage with supported robots.
+ *
+ *  This class involves all aspects of the forward kinematics:
+ *  calculations concerning locations and orientations in space given
+ *  a known set of joint configurations.  There is a global
+ *  instantiation of Kinematics named ::kine, which can be used to
+ *  perform these calculations regarding the joint positions currently
+ *  in ::state.
+ *
+ *  To perform kinematics on a hypothetical set of joint values,
+ *  please see PostureEngine or its subclasses.  PostureEngine also
+ *  includes inverse kinematic functions, which will allow you to
+ *  determine joint angles in order to reach a given point.
+ *  
+ *  The underlying ROBOOP library does not currently handle branching
+ *  kinematic chains - in other words, each limb of the robot is a
+ *  separate Robot as far as ROBOOP is concerned.  This class
+ *  interfaces the Tekkotsu array index approach to referencing joints
+ *  with ROBOOP's chain based hierarchy.
+ *  
+ *  Thus, wherever a link or reference frame index is requested, you
+ *  can simply supply one of the output indexes in the usual manner:
+ *  @code kine->frameToBase(HeadOffset+TiltOffset); @endcode
+ *
+ *  However, there are also a number of points on the body which are
+ *  not joints, but should have their own reference frames, such as
+ *  the base frame, or the camera.  These frames have their own
+ *  indices, listed in the robot info file for the model in question
+ *  (such as ERS7Info.h), with names ending in @c FrameOffset.
+ *  @code kine->frameToBase(CameraFrameOffset); @endcode
+ *
+ *  Since newmat matrix library is used by ROBOOP, you will need to
+ *  pass and receive information in newmat matrices.  This class
+ *  provides #pack and #unpack functions which can convert individual
+ *  x,y,z variables into a NEWMAT::ColumnVector, and vice versa.
+ *  However, for readability of your code and long-term ease of use,
+ *  we recommend embracing the newmat data structures directly when
+ *  appropriate.
+ *  @code
+ *  // Find the ray from the camera to whatever the near-field IR is hitting:
+ *  // x and y will be in the range -1 to 1 for resolution layer independence
+ *  // This ignores lens distortion - just proof of concept
+ *  NEWMAT::Matrix T = kine->frameToFrame(NearIRFrameOffset,CameraFrameOffset);
+ *  NEWMAT::ColumnVector camera_ray = T*Kinematics::pack(0,0,state->sensors[NearIRDistOffset]);
+ *  float x=atan(camera_ray(1),camera_ray(3))/config->vision.horizFOV/2;
+ *  float y=atan(camera_ray(2),camera_ray(3))/config->vision.vertFOV/2;
+ *  @endcode
+ *  
+ *  Finally, for each model we have created a database of "interest points",
+ *  locations of notable interest on the body of the robot.  These may be of
+ *  use to people attempting to use the limbs to manipulate objects.
+ *  To access these interest points, simply call either #getLinkInterestPoint
+ *  or #getFrameInterestPoint with the name of the interest point, obtained
+ *  from the <a href="http://www.tekkotsu.org/Kinematics.html">diagrams</a>.
+ *
+ *  Note that you can pass a comma separated list of interest point names
+ *  and the result will be the midpoint of those interest points:
+ *  @code kine->getLinkInterestPoint(BaseFrameOffset,"LowerInnerFrontLFrShin,LowerOuterFrontLFrShin"); @endcode
+ *  
+ *  @see PostureEngine for inverse kinematics
+ */
+class Kinematics {
+public:
+	//!Constructor, pass the full path to the kinematics configuration file
+	Kinematics() : chains(), chainMaps() {
+		init();
+	}
 
-#define RAD(deg) (((deg) * M_PI ) / 180.0)
-#define DEG(rad) (((rad) * 180.0) / M_PI )
+	//!Destructor
+	virtual ~Kinematics() {}
 
-extern const double rotator_min ;
-extern const double rotator_max ;
-extern const double shoulder_min;
-extern const double shoulder_max;
-extern const double knee_max    ;
-extern const double knee_min    ;
 
-extern const double rotator_kmin ;
-extern const double rotator_kmax ;
-extern const double shoulder_kmin;
-extern const double shoulder_kmax;
-extern const double knee_kmax    ;
-extern const double f_knee_kmin  ;
-extern const double h_knee_kmin  ;
 
-extern const double tail_min;
-extern const double tail_max;
+	//! Returns a matrix for transforming from link @a j to base frame
+	/*! @param[in]  j the link number, see class notes for values */
+	NEWMAT::ReturnMatrix linkToBase(unsigned int j);
 
-extern const double head_tilt_min;
-extern const double head_tilt_max;
-extern const double head_pan_min ;
-extern const double head_pan_max ;
-extern const double head_roll_min;
-extern const double head_roll_max;
+	//! Returns a matrix for transforming from frame @a j to base frame
+	/*! @param[in]  j the frame number, see class notes for values */
+	NEWMAT::ReturnMatrix frameToBase(unsigned int j);
 
-//! holds the current location of the body, as a delta from when walking started
-/*! @todo get rid of this */
-struct BodyPosition{
-	//! constructor
-	BodyPosition() : loc(), angle() {}
-  vector3d loc;   //!< position of the center of the body
-	vector3d angle; //!< angle of the center of the body
-};
+	//! Returns a matrix for transforming from the base frame to link @a j
+	/*! @param[in]  j the link number, see class notes for values */
+	NEWMAT::ReturnMatrix baseToLink(unsigned int j);
 
-const vector3d body_to_neck    ( 75.00,  0.00,  50.00);
-const vector3d neck_to_camera  ( 65.00,  0.00,  48.00);
+	//! Returns a matrix for transforming from the base frame to frame @a j
+	/*! @param[in]  j the frame number, see class notes for values */
+	NEWMAT::ReturnMatrix baseToFrame(unsigned int j);
 
-void KinClearErrors();
-int KinGetErrors();
+	//! Returns a matrix for transforming from link @a ij to link @a oj frame
+	/*! @param[in]  ij the link number to convert from, see class notes for values
+	 *  @param[in]  oj the link number to convert to, see class notes for values */
+	NEWMAT::ReturnMatrix linkToLink(unsigned int ij, unsigned int oj);
 
-void GetLegAngles(double *angles,vector3d target,int leg);
-void GetLegAngles(double *angles,vector3d target[4],
-                  double body_angle,double body_height);
-void GetLegAngles(double *angles,vector3d target[4],BodyPosition &bp);
+	//! Returns a matrix for transforming from link @a ij to frame @a oj
+	/*! @param[in]  ij the link number to convert from, see class notes for values
+	 *  @param[in]  oj the frame number to convert to, see class notes for values */
+	NEWMAT::ReturnMatrix linkToFrame(unsigned int ij, unsigned int oj);
 
-void GetLegAngles(double *angles,vector3d target,BodyPosition &bp,int leg);
-void GetLegPosition(vector3d& p,const double* ang,int leg);
-void GetLegPosition(vector3d& p, const double* ang, BodyPosition &bp,int leg);
+	//! Returns a matrix for transforming from frame @a ij to link @a oj
+	/*! @param[in]  ij the frame number to convert from, see class notes for values
+	 *  @param[in]  oj the link number to convert to, see class notes for values */
+	NEWMAT::ReturnMatrix frameToLink(unsigned int ij, unsigned int oj);
+
+	//! Returns a matrix for transforming from frame @a ij to frame @a oj frame
+	/*! @param[in]  ij the frame number to convert from, see class notes for values
+	 *  @param[in]  oj the frame number to convert to, see class notes for values */
+	NEWMAT::ReturnMatrix frameToFrame(unsigned int ij, unsigned int oj);
+
+
+
+	//! Returns the location of a named point and the link it is attached to
+	/*! @param[in]  name   the name of the interest point; varies by model, <a href="http://www.tekkotsu.org/Kinematics.html">see the diagrams</a> for your model.
+	 *  @param[out] j      on exit, joint index of the link, or -1U if not found
+	 *  @param[out] ip     on exit, a homogenous column vector of the requested point
+	 *
+	 *  If @a name is not found, j will be -1 and ip will be all 0's. */
+	void getInterestPoint(const std::string& name, unsigned int& j, NEWMAT::Matrix& ip);
+
+	//! Returns the location of a named point, relative to any desired reference frame
+	/*! @param[in]  frame  the desired reference frame to give results in
+	 *  @param[in]  name   the name of the interest point; varies by model, <a href="http://www.tekkotsu.org/Kinematics.html">see the diagrams</a> for your model.
+	 *
+	 *  You can pass a comma separated list of interest point names and the result will be the midpoint of those IPs */
+	NEWMAT::ReturnMatrix getFrameInterestPoint(unsigned int frame, const std::string& name);
+
+	//! Returns the location of a named point, relative to any desired reference frame
+	/*! @param[in]  link   the desired link frame to give results in
+	 *  @param[in]  name   the name of the interest point; varies by model, <a href="http://www.tekkotsu.org/Kinematics.html">see the diagrams</a> for your model.
+	 *
+	 *  You can pass a comma separated list of interest point names and the result will be the midpoint of those IPs */
+	NEWMAT::ReturnMatrix getLinkInterestPoint(unsigned int link, const std::string& name) {
+		NEWMAT::ColumnVector p=frameToLink(link,link)*getFrameInterestPoint(link,name);
+		p.Release(); return p;
+	}
 
-void GetBodyLocation(vector3d &ball,vector3d &toe,const double *ang,int leg);
 
-// get the tilt,pan,roll angles to point the head towards the target assuming 
-//   the given body_angle/body_height
-void GetHeadAngles(double *angles,vector3d target,
-                   double body_angle,double body_height);
-// converts the camera relative position "point" to a robot centric (under base of neck) position
-//  using the given head angles (tilt/pan/roll) and body_angle and body_height
-vector3d RunForwardModel(double *angles, 
-                         double body_angle, double body_height, 
-                         vector3d point);
-// gets the location of the camera and basis vectors corresponding to the directions of the camera's
-//  z,-y,x corrdinate axis
-void GetHeadPosition(vector3d &location, vector3d &direction, vector3d &up, vector3d &right,
-                     double *angles, double body_angle, double body_height);
 
+	//! Find the leg which is in least contact with ground (as best we can anyway)
+	/*! This can be either based on gravity vector from accelerometer readings,
+	 *  or if that may be unreliable due to being in motion, we could do some basic
+	 *  balance modeling.
+	 *  @return index of leg which is highest in reference to gravity vector */
+	LegOrder_t findUnusedLeg(const NEWMAT::ColumnVector& down);
+
+	//! Find the ground plane (by fitting plane to legs other the one specified by findUnusedLeg(down))
+	/*! This function merely calls the other version of calculateGroundPlane with the current
+	 *  gravity vector as the "down" vector.
+	 *  @return vector of the form @f$p_1x + p_2y + p_3z = p_4@f$, relative to the base frame */
+	NEWMAT::ReturnMatrix calculateGroundPlane();
+
+	//! Find the ground plane (by fitting plane to legs other the one specified by findUnusedLeg(down))
+	/*! @return vector of the form @f$p_1x + p_2y + p_3z = p_4@f$, relative to the base frame */
+	NEWMAT::ReturnMatrix calculateGroundPlane(const NEWMAT::ColumnVector& down);
+
+	//! Find the point of intersection between a ray and a plane
+	/*! @param j is the link number the ray is relative to
+	 *  @param r_j is the line through the origin, in homogenous coordinates
+	 *  @param b is the link number the plane is relative to (probably BaseFrameOffset)
+	 *  @param p_b represents the plane to be intersected
+	 *  @param f is the link number the results should be relative to
+	 *
+	 *  @a p_b should be of the form @f$p_1x + p_2y + p_3z = p_4@f$
+	 *  @return homogenous coordinate of intersection (may be infinity) */
+	NEWMAT::ReturnMatrix projectToPlane(unsigned int j, const NEWMAT::ColumnVector& r_j,
+	                                    unsigned int b, const NEWMAT::ColumnVector& p_b,
+	                                    unsigned int f);
+
+
+	//! A simple utility function, converts x,y,z,h to a NEWMAT::ColumnVector
+	/*! @param[in]  x the value for the first row
+	 *  @param[in]  y the value for the second row
+	 *  @param[in]  z the value for the third row
+	 *  @param[in]  h the value for the fourth row (defaults to 1 if not specified)
+	 *  @return @f$ \left[\begin{array}{c} x\\y\\z\\h\\ \end{array}\right] @f$ */
+	static NEWMAT::ReturnMatrix pack(float x, float y, float z, float h=1) {
+		NEWMAT::ColumnVector m(4);
+		m(1)=x; m(2)=y; m(3)=z; m(4)=h;
+		m.Release(); return m;
+	}
+	//! A simple utility function, pulls the first 3 rows of the first column, divides each by the fourth row, and stores into ox, oy, and oz
+	/*! @param[in]  m  the matrix to unpack (only uses first column)
+	 *  @param[out] ox set to the first row of the first column of @a m, divided by fourth row
+	 *  @param[out] oy set to the second row of the first column of @a m, divided by fourth row
+	 *  @param[out] oz set to the third row of the first column of @a m, divided by fourth row */
+	static void unpack(NEWMAT::Matrix m, float& ox, float& oy, float& oz) {
+		ox=m(1,1)/m(4,1); oy=m(2,1)/m(4,1); oz=m(3,1)/m(4,1);
+	}
+	//! A simple utility function, pulls the first 4 rows of the first column, stores into ox, oy, oz, oh
+	/*! @param[in]  m  the matrix to unpack (only uses first column)
+	 *  @param[out] ox set to the first row of the first column of @a m
+	 *  @param[out] oy set to the second row of the first column of @a m
+	 *  @param[out] oz set to the third row of the first column of @a m
+	 *  @param[out] oh set to the fourth row of the first column of @a m */
+	static void unpack(NEWMAT::Matrix m, float& ox, float& oy, float& oz, float& oh) {
+		ox=m(1,1); oy=m(2,1); oz=m(3,1); oh=m(4,1);
+	}
+	
+	static ROBOOP::Config * getConfig() { return roconfig; }
+	
+protected:
+	//! Called by constructors to do basic setup - first call will read Config::motion_config::kinematics from disk, future initializes reuse static roconfig
+	void init();
+	
+	//! Returns the location of a named point, relative to the link it is attached to
+	/*! @param[in]  name   the name of the interest point; varies by model, <a href="http://www.tekkotsu.org/Kinematics.html">see the diagrams</a> for your model.
+	 *  @param[out] c      on exit, chain index the IP is on
+	 *  @param[out] l      on exit, link index the IP is on
+	 *  @param[out] ip     on exit, a homogenous column vector of the requested point
+	 *
+	 *  If @a name is not found, @a c and @a l will be -1 and @a ip will be all 0's. 
+	 *  This internal version of the function allows us to use @a c and @a l, ourselves,
+	 *  but users will probably want to use the getInterestPoint(name,j,ip) version */
+	void getInterestPoint(const std::string& name, unsigned int& c, unsigned int& l, NEWMAT::Matrix& ip);
+	
+	//! Called at the beginning of each function which accesses ROBOOP computations - should make sure the ROBOOP structures are up to date with Tekkotsu structures
+	/*! This class will pull current values from WorldState, but it is expected
+	 *  that subclasses (i.e. PostureEngine) will want to provide their own joint values.
+	 *  Updates from link 1 through link @a l.
+	 *  @param[in] c the chain to update
+	 *  @param[in] l the last link to update (later links in the chain are left untouched) */
+	virtual void update(unsigned int c, unsigned int l);
+
+	//! converts a Tekkotsu output index to a chain and link
+	/*! @param[in]  tkout the tekkotsu index to lookup
+	 *  @param[out] c set to the chain index that @a tkout is in
+	 *  @param[out] l set to the link in @a c corresponding to @a tkout */
+	bool lookup(unsigned int tkout, unsigned int& c, unsigned int& l) {
+		if(tkout>=NumReferenceFrames) {
+			serr->printf("ERROR Kinematics: illegal link %d\n",l);
+			return false;
+		}
+		if(jointMaps[tkout].chain>=chains.size()) {
+			serr->printf("ERROR Kinematics: no chain available for link %d\n",l);
+			return false;
+		}
+		c=jointMaps[tkout].chain;
+		l=jointMaps[tkout].link;
+		return true;
+	}
+
+	//! A separate ROBOOP::Robot instantiation for each chain since ROBOOP package doesn't support branching chains (which would be rather difficult to implement well)
+	std::vector<ROBOOP::Robot*> chains;
+
+	//! holds mapping for each chain's links back to the tekkotsu outputs they represent
+	std::vector< std::vector<unsigned int> > chainMaps;
+	
+	//! Allows mapping from tekkotsu output index to chain and link indicies
+	struct JointMap {
+		JointMap() : chain(-1U), link(-1U) {} //!< constructor
+		JointMap(unsigned int c, unsigned int l) : chain(c), link(l) {} //!< constructor
+		unsigned int chain; //! the chain index
+		unsigned int link; //!< the link index
+	};
+	//! holds the position and attached link of a given interest point
+	struct InterestPoint {
+		InterestPoint() : x(), y(), z(), chain(), link() {} //!< constructor
+		InterestPoint(float x_, float y_, float z_, unsigned int chain_, unsigned int link_)
+			: x(x_), y(y_), z(z_), chain(chain_), link(link_) {} //!< constructor
+		float x; //!< x value
+		float y; //!< y value
+		float z; //!< z value
+		unsigned int chain; //!< chain containing @a link
+		int link; //!< link in @a chain
+	};
+
+	//! holds mapping from tekkotsu output index to chain and link indicies
+	JointMap jointMaps[NumReferenceFrames];
+	
+	//! cache of the configuration of the robot for rapid initialization (so we don't have to re-read from disk)
+	static ROBOOP::Config * roconfig;
+	//! allows us to use the STL hash_map with strings
+	struct hashstring {
+		//! hashes a string by multiplying current total by 5, add new character
+		/*! not my idea, this is what the STL library does for char*, i've just reimplemented it for strings */
+		size_t operator()(const string& s) const {
+			unsigned long h=0;
+			for(string::size_type x=s.size(); x!=0; x--)
+				h=h*5+s[x];
+			return (size_t)h;
+		}
+	};
+	//! we'll be using the hash_map to store named interest points
+	typedef __gnu_cxx::hash_map<const string,InterestPoint,hashstring> InterestPointMap;
+	//! these interest points are shared by all Kinematics classes (i.e. all PostureEngines)
+	/*! this is to reduce initialization time, but does mean one robot can't do
+	 *  kinematic calculations regarding a different model robot...  */
+	static InterestPointMap * ips;
+};
+
+//! a global instance of Kinematics, joint values reference those of WorldState so users can easily query the current spatial locations of joints
+extern Kinematics * kine;
 
 /*! @file
- * @brief Functions to provide kinematics calculations
- * @author CMU RoboSoccer 2001-2002 (Creator)
- * 
- * @verbinclude CMPack_license.txt
+ * @brief Describes Kinematics, which provides access to the mathematical functionality of the roboop package using Tekkotsu data structures
+ * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.23 $
  * $State: Exp $
- * $Date: 2004/02/26 01:02:49 $
+ * $Date: 2004/10/19 17:06:31 $
  */
 
 #endif
-// __KINEMATICS_H__
Index: Motion/LedEngine.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/LedEngine.cc,v
retrieving revision 1.12
retrieving revision 1.15
diff -u -d -r1.12 -r1.15
--- Motion/LedEngine.cc	3 Feb 2004 01:17:57 -0000	1.12
+++ Motion/LedEngine.cc	12 Sep 2004 04:22:37 -0000	1.15
@@ -8,29 +8,62 @@
 /*! This is "Mimic the number" style */
 const LEDBitMask_t LedEngine::ERS210numMasks[11] = {
 	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopBrLEDMask, //0
+	
 	ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopLLEDMask,  //1
+	
 	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //2
-	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //3
+	
+	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::TopLLEDMask
+	|ERS210Info::TopBrLEDMask, //3
+	
 	ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask,  //4
+
 	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopBrLEDMask, //5
-	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopBrLEDMask, //6
+
+	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask
+	|ERS210Info::TopRLEDMask|ERS210Info::TopBrLEDMask, //6
+
 	ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask,  //7
-	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //8
-	ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask,  //9
+
+	ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask
+	|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //8
+
+	ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask
+	|ERS210Info::TopBrLEDMask,  //9
+
 	ERS210Info::BotLLEDMask //.
 };
 /*! This is "Count the dots" style */
 const LEDBitMask_t LedEngine::ERS220numMasks[11] = {
 	ERS220Info::ModeLEDMask, //0
+
 	ERS220Info::FaceBackLeftLEDMask, //1
+
 	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask, //2
+
 	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask, //3
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask, //4
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask, //5
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask, //6
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask|ERS220Info::FaceFrontALEDMask, //7
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask|ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask, //8
-	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask|ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask|ERS220Info::FaceFrontCLEDMask, //9
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask, //4
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask, //5
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask, //6
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
+	|ERS220Info::FaceFrontALEDMask, //7
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
+	|ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask, //8
+
+	ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
+	|ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
+	|ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask|ERS220Info::FaceFrontCLEDMask, //9
+
 	ERS220Info::FaceFrontLeftLEDMask //.
 };
 /*
@@ -53,19 +86,37 @@
 const LEDBitMask_t LedEngine::ERS7numMasks[11] = {
 	0, //0
 	(ERS7Info::FaceLEDPanelMask<<11), //1
+
 	(ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<< 5), //2
+
 	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<<11)|(ERS7Info::FaceLEDPanelMask<< 3), //3
-	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9), //4
-	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //5
-	(ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7), //6
-	(ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<<11), //7
-	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9), //8
-	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //9
+
+	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)
+	|(ERS7Info::FaceLEDPanelMask<<9), //4
+
+	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)
+	|(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //5
+
+	(ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)
+	|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7), //6
+
+	(ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)
+	|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
+	|(ERS7Info::FaceLEDPanelMask<<11), //7
+
+	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)
+	|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
+	|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9), //8
+
+	(ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)
+	|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
+	|(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //9
+
 	(ERS7Info::FaceLEDPanelMask<< 1) //.
 };
 
 
-LedEngine::LedEngine() : numCycling(0), dirty(true), dirtyTime((unsigned int)-1) {
+LedEngine::LedEngine() : dirty(true), numCycling(0), nextFlashEnd((unsigned int)-1) {
 	for(unsigned int i=0; i<NumLEDs; i++) {
 		infos[i].flashtime=0;
 		infos[i].starttime=0;
@@ -73,45 +124,53 @@
 	clear();
 }
 
+void LedEngine::recalcFlashEnd(void) {
+  unsigned int t = get_time();
+  nextFlashEnd=(unsigned int)-1;
+  for(unsigned int i=0; i<NumLEDs; i++)
+    if(infos[i].flashtime>t && nextFlashEnd>infos[i].flashtime)
+      nextFlashEnd=infos[i].flashtime;
+}
+
 int LedEngine::isDirty() {
 	unsigned int t = get_time();
-	if(t>dirtyTime) {
-		dirty=true;
-		dirtyTime=(unsigned int)-1;
-		for(unsigned int i=0; i<NumLEDs; i++)
-			if(infos[i].flashtime>t && dirtyTime>infos[i].flashtime)
-				dirtyTime=infos[i].flashtime;
-	}
-	return (dirty || numCycling>0);
+	if(t>nextFlashEnd) {
+	  dirty=true;
+	  recalcFlashEnd();
+	};
+	return dirty;
 }
 
 int LedEngine::updateLEDs(const MotionCommand* caller, LEDBitMask_t mask/*=AllLEDMask*/) {
 	unsigned int t = get_time();
+	if (t>nextFlashEnd) recalcFlashEnd();
 	for(unsigned int i=0; i<NumLEDs; i++)
 		if((mask>>i)&1)
 			for(unsigned int f=0; f<NumFrames; f++)
 				motman->setOutput(caller, i+LEDOffset,calcValue(i,t+f*FrameTime),f);
 	bool tmp=dirty;
-	dirty=false;
+	dirty = numCycling>0;
 	return tmp;
 }
 
 int LedEngine::updateLEDs(OutputCmd cmds[NumLEDs]) {
 	unsigned int t = get_time();
+	if (t>nextFlashEnd) recalcFlashEnd();
 	for(unsigned int i=0; i<NumLEDs; i++)
 			cmds[i].value=calcValue(i,t);
 	bool tmp=dirty;
-	dirty=false;
+	dirty = numCycling>0;
 	return tmp;
 }
 
 int LedEngine::updateLEDFrames(OutputCmd cmds[NumLEDs][NumFrames]) {
 	unsigned int t = get_time();
+	if (t>nextFlashEnd) recalcFlashEnd();
 	for(unsigned int i=0; i<NumLEDs; i++)
 		for(unsigned int f=0; f<NumFrames; f++)
 			cmds[i][f].value=calcValue(i,t+f*FrameTime);
 	bool tmp=dirty;
-	dirty=false;
+	dirty = numCycling>0;
 	return tmp;
 }
 
@@ -142,8 +201,8 @@
 void LedEngine::cflash(LEDBitMask_t leds, float value, unsigned int ms) {
 	dirty=true;
 	unsigned int t = get_time();
-	if(t+ms<dirtyTime)
-		dirtyTime=t+ms;
+	if(t+ms<nextFlashEnd)
+	  nextFlashEnd=t+ms;
 	for(unsigned int i=0; i<NumLEDs; i++) {
 		infos[i].flashvalue=((leds>>i)&1)*value;
 		infos[i].flashtime=t+ms;
@@ -153,8 +212,8 @@
 	if(leds!=0) {
 		dirty=true;
 		unsigned int t = get_time();
-		if(t+ms<dirtyTime)
-			dirtyTime=t+ms;
+		if(t+ms<nextFlashEnd)
+		  nextFlashEnd=t+ms;
 		for(unsigned int i=0; i<NumLEDs; i++)
 			if((leds>>i)&1) {
 				infos[i].flashvalue=value;
@@ -166,8 +225,8 @@
 	if(leds!=0) {
 		dirty=true;
 		unsigned int t = get_time();
-		if(t+ms<dirtyTime)
-			dirtyTime=t+ms;
+		if(t+ms<nextFlashEnd)
+		  nextFlashEnd=t+ms;
 		for(unsigned int i=0; i<NumLEDs; i++)
 			if((leds>>i)&1) {
 				infos[i].flashvalue=calcFlash(calcValue(i,t));
@@ -332,9 +391,9 @@
  * @brief Implements LedEngine, which provides basic LED effects to anything that inherits or instantiates it
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.15 $
  * $State: Exp $
- * $Date: 2004/02/03 01:17:57 $
+ * $Date: 2004/09/12 04:22:37 $
  */
Index: Motion/LedEngine.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/LedEngine.h,v
retrieving revision 1.13
retrieving revision 1.17
diff -u -d -r1.13 -r1.17
--- Motion/LedEngine.h	9 Feb 2004 22:45:28 -0000	1.13
+++ Motion/LedEngine.h	12 Sep 2004 04:22:37 -0000	1.17
@@ -14,8 +14,8 @@
 /*! Provides a collection of special effects so that the code can be
  *  reused various places as feedback to to the user.
  *
- * Cycling ("pulsing") and single-value setting are mutually exclusive
- * - one will cut off the other
+ * Cycling ("pulsing") and single-value setting are mutually exclusive;
+ * one will cut off the other
  *
  * A flash will invert and override the current setting, so that it
  * will "reset" after the flash.  Flashes change mid-range values to
@@ -31,8 +31,8 @@
  *
  * The ERS-220 and ERS-7 have enough LEDs that they just use a "count
  * the lights" style of display instead of this pseudo-arabic display.
- * (look close to see that green bar LED at the top of the 210, this
- * isn't actually too hard to read once you "see" it)
+ * (look close to see that green bar LED at the top of the 210, which 
+ * doesn't show up well in the camera image for some reason. )
  */
 
 class LedEngine {
@@ -55,7 +55,10 @@
 	/*! @param cmds on input, used for weight values - on return, holds the resulting OutputCmd's*/
 	int updateLEDFrames(OutputCmd cmds[NumLEDs][NumFrames]);
 	
-	//!returns true if there are changes since the last updateLEDs()
+	//! recalculates #nextFlashEnd so we can tell when a flash has completed
+	void recalcFlashEnd();
+
+	//! returns true if there are changes since the last updateLEDs()
 	int isDirty();
 
 	//!sets the leds specified by @a leds to the inverse of their current value
@@ -160,20 +163,20 @@
 	};
 	
 	LEDInfo infos[NumLEDs]; //!< the information regarding each of the LEDs
+	bool dirty;             //!< true if changes since last updateLEDs: either at least one LED is cycling or a flash has begun/ended
 	unsigned int numCycling;//!< the number of LEDs currently cycling (if non-zero, always dirty)
-	bool dirty;             //!< true if changes since last updateLEDs
-	unsigned int dirtyTime; //!< the time at which it becomes dirty again (if flashing)
+	unsigned int nextFlashEnd; //!< the soonest time a flash will end (and we'll become dirty)
 };
 	
 /*! @file
  * @brief Describes LedEngine, which provides basic LED effects to anything that inherits or instantiates it
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.13 $
+ * $Revision: 1.17 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/09/12 04:22:37 $
  */
 
 #endif
Index: Motion/LedMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/LedMC.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Motion/LedMC.h	25 Sep 2003 15:27:23 -0000	1.6
+++ Motion/LedMC.h	10 Sep 2004 22:25:15 -0000	1.7
@@ -2,6 +2,8 @@
 #ifndef INCLUDED_LedMC_h
 #define INCLUDED_LedMC_h
 
+#include "Events/EventBase.h"
+#include "Events/EventRouter.h"
 #include "MotionCommand.h"
 #include "LedEngine.h"
 #include "OutputCmd.h"
@@ -13,43 +15,52 @@
  *  just use the engine component to do all the work. */
 class LedMC : public MotionCommand, public LedEngine {
  public:
-	//! constructor
-	LedMC() : MotionCommand(), LedEngine() { setWeights(AllLEDMask,1); }
-	//! destructor
-	virtual ~LedMC() {}
+  //! constructor
+  LedMC() : MotionCommand(), LedEngine(), notified(true) { setWeights(AllLEDMask,1); }
+  //! destructor
+  virtual ~LedMC() {}
+  
+  //! updates the cmds from LedEngine::updateLEDs()
+  virtual int updateOutputs() {
+    updateLEDFrames(cmds);
+    for(unsigned int i=0; i<NumLEDs; i++)
+      if(cmds[i][0].weight!=0)
+	motman->setOutput(this,i+LEDOffset,cmds[i]);
+    if (nextFlashEnd < (unsigned int)-1)  // do we have a flash in progress?
+      notified=false;
+    else if (notified == false) {  // flash has ended (nextFlashEnd == -1), but notice not yet sent
+      postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
+      notified=true;
+    };
+    return NumLEDs;
+  }
 
-	//! updates the cmds from LedEngine::updateLEDs()
-	virtual int updateOutputs() {
-		updateLEDFrames(cmds);
-		for(unsigned int i=0; i<NumLEDs; i++)
-			if(cmds[i][0].weight!=0)
-				motman->setOutput(this,i+LEDOffset,cmds[i]);
-		return NumLEDs;
-	}
-	virtual int isDirty() { return LedEngine::isDirty(); }
-	virtual int isAlive() { return true; } //!< @todo let's make this smarter so you can flash the LED's and have it autoprune
+  virtual int isDirty() { return LedEngine::isDirty(); }
 
-	//! Sets the JointCmd::weight of the LEDs specified by @a leds to @a weight
-	void setWeights(LEDBitMask_t leds, float weight) {
-		for(unsigned int i=0; i<NumLEDs; i++)
-			if((leds>>i)&1)
-				for(unsigned int f=0; f<NumFrames; f++)
-					cmds[i][f].weight=weight;
-	}
+  virtual int isAlive() { return LedEngine::isDirty() || nextFlashEnd < (unsigned int)-1; }
+
+  //! Sets the JointCmd::weight of the LEDs specified by @a leds to @a weight
+  void setWeights(LEDBitMask_t leds, float weight) {
+    for(unsigned int i=0; i<NumLEDs; i++)
+      if((leds>>i)&1)
+	for(unsigned int f=0; f<NumFrames; f++)
+	  cmds[i][f].weight=weight;
+  }
 
 protected:
-	OutputCmd cmds[NumLEDs][NumFrames]; //!< needed to store weight values of LEDs (useful to mark LEDs as unused)
+  OutputCmd cmds[NumLEDs][NumFrames]; //!< needed to store weight values of LEDs (useful to mark LEDs as unused)
+  bool notified; //!< set to true when we've posted a status event for completion of a flash/cflash
 };
 
 /*!@file
  * @brief Defines LedMC, which provides a basic MotionCommand wrapper to LedEngine
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.6 $
- * $State: Rel $
- * $Date: 2003/09/25 15:27:23 $
+ * $Revision: 1.7 $
+ * $State: Exp $
+ * $Date: 2004/09/10 22:25:15 $
  */
 
 #endif
Index: Motion/MotionManager.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/MotionManager.cc,v
retrieving revision 1.34
retrieving revision 1.38
diff -u -d -r1.34 -r1.38
--- Motion/MotionManager.cc	7 Feb 2004 01:02:29 -0000	1.34
+++ Motion/MotionManager.cc	17 Oct 2004 01:16:11 -0000	1.38
@@ -19,11 +19,7 @@
 const float MotionManager::kHighPriority       = 50;
 const float MotionManager::kEmergencyPriority  = 100;
 
-#ifndef PLATFORM_APERIOS
-using std::cout;
-using std::endl;
-#endif
-
+using namespace std;
 
 //! just for convenience
 typedef unsigned int uint;
@@ -497,19 +493,43 @@
 	return dirty;
 }
 
-// documentation for this function is at the end of the file
+/*! @deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises */
 MotionManager::MC_ID
 MotionManager::addMotion(const SharedObjectBase& sm) {
-	//cout << "addMotion...";
-	while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; } //Wait for everyone to register
-	func_begin();
-	//cout << cmdlist.size() << " exist..." << endl;
-	//	cout << id << "..." << flush;
+	return doAddMotion(sm,true,kStdPriority);
+}
+/*! @deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises */
+MotionManager::MC_ID 
+MotionManager::addMotion(const SharedObjectBase& sm, bool autoprune) {
+	return doAddMotion(sm,autoprune,kStdPriority);
+}
+/*! @deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises */
+MotionManager::MC_ID
+MotionManager::addMotion(const SharedObjectBase& sm, float priority) {
+	return doAddMotion(sm,true,priority);
+}
+/*! @deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises */
+MotionManager::MC_ID 
+MotionManager::addMotion(const SharedObjectBase& sm, float priority, bool autoprune) {
+	return doAddMotion(sm,autoprune,priority);
+}
+/*! We have made this function protected because it's more readable if you
+ *  call addPrunableMotion() or addPersistentMotion() instead... we decided
+ *  requiring people to pass a true/false arguement wouldn't make it clear
+ *  what that true/false was controlling. */
+MotionManager::MC_ID 
+MotionManager::doAddMotion(const SharedObjectBase& sm, bool autoprune, float priority) {
 	MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
 	if(mc==NULL) {
 		cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
 		return invalid_MC_ID;
 	}
+	mc->setAutoPrune(autoprune);
+	//cout << "addMotion...";
+	while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; } //Wait for everyone to register
+	func_begin();
+	//cout << cmdlist.size() << " exist..." << endl;
+	//	cout << id << "..." << flush;
 	MC_ID mc_id = pop_free();
 	if(mc_id==cmdlist.end()) {
 		cout << "MotionManager::addMotion() - Out of room, could not add" << endl;
@@ -521,7 +541,7 @@
 	cmdlist[mc_id].rcr[_MMaccID]->AddReference();
 	//cout << "addMotion()NOW: sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
 	cmdlist[mc_id].lastAccessor=_MMaccID;
-	cmdlist[mc_id].priority=kStdPriority;
+	cmdlist[mc_id].priority=priority;
 	mc->setAdd(mc_id);
 	OStatus err;
 	/*{
@@ -537,38 +557,6 @@
 	//	cout << "addMotion-done" << endl;
 	return func_end(mc_id);
 }
-MotionManager::MC_ID 
-MotionManager::addMotion(const SharedObjectBase& sm, float priority) {
-	func_begin();
-	MC_ID mcid=addMotion(sm);
-	if(mcid!=end())
-		setPriority(mcid,priority);
-	return func_end(mcid);
-}
-MotionManager::MC_ID 
-MotionManager::addMotion(const SharedObjectBase& sm, bool autoprune) {
-	MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
-	if(mc==NULL) {
-		cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
-		return invalid_MC_ID;
-	}
-	mc->setAutoPrune(autoprune);
-	return addMotion(sm); 
-}
-MotionManager::MC_ID 
-MotionManager::addMotion(const SharedObjectBase& sm, float priority, bool autoprune) {
-	func_begin();
-	MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
-	if(mc==NULL) {
-		cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
-		return invalid_MC_ID;
-	}
-	mc->setAutoPrune(autoprune);
-	MC_ID mcid=addMotion(sm);
-	if(mcid!=end())
-		setPriority(mcid,priority);
-	return func_end(mcid);
-}
 
 void
 MotionManager::receivedMsg(const ONotifyEvent& event) {
@@ -588,7 +576,7 @@
 			//should be able to do a nice dynamic cast instead of a static one
 			// but it gives NULL for some reason - i blame having to do the fork trick
 			cmdlist[mc_id].baseaddrs[_MMaccID]=static_cast<MotionCommand*>(mminfo);
-			erouter->postEvent(new EventBase(EventBase::motmanEGID,mc_id,EventBase::activateETID,00));
+			erouter->postEvent(new EventBase(EventBase::motmanEGID,mc_id,EventBase::activateETID,0));
 			cmdlist[mc_id].baseaddrs[_MMaccID]->DoStart();
 		} break;
 		case MotionManagerMsg::deleteMotion: {
@@ -650,7 +638,7 @@
 	func_begin();
 	checkoutMotion(mcid,true);
 	cmdlist[mcid].baseaddrs[_MMaccID]->DoStop();
-	erouter->postEvent(new EventBase(EventBase::motmanEGID,mcid,EventBase::deactivateETID,00));
+	erouter->postEvent(new EventBase(EventBase::motmanEGID,mcid,EventBase::deactivateETID,0));
 #ifdef PLATFORM_APERIOS
 	MotionManagerMsg dmsg;
 	dmsg.setDelete(mcid);
@@ -678,10 +666,10 @@
 	for(uint u = pidchanges.begin(); u!=pidchanges.end(); u=pidchanges.next(u)) {
 		if(pidchanges[u].joint==joint) { //found it
 			for(uint i=0; i<3; i++) {
-				pidchanges[i].pids[i]=pids[i];
+				pidchanges[u].pids[i]=pids[i];
 				if(pids[i]!=state->pids[joint][i]) { //see if we're setting back to current PID
 					for(i++; i<3; i++) //we aren't, copy over the rest
-						pidchanges[i].pids[i]=pids[i];
+						pidchanges[u].pids[i]=pids[i];
 					func_end();
 					return;
 				}
@@ -761,9 +749,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.34 $
+ * $Revision: 1.38 $
  * $State: Exp $
- * $Date: 2004/02/07 01:02:29 $
+ * $Date: 2004/10/17 01:16:11 $
  */
 
 
Index: Motion/MotionManager.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/MotionManager.h,v
retrieving revision 1.20
retrieving revision 1.23
diff -u -d -r1.20 -r1.23
--- Motion/MotionManager.h	9 Feb 2004 22:45:28 -0000	1.20
+++ Motion/MotionManager.h	18 Oct 2004 23:10:26 -0000	1.23
@@ -35,7 +35,7 @@
  *  one line:
  *
  *  @code
- *  motman->addMotion(SharedObject<YourMC>([arg1,[arg2,...]]) [, priority [, autoprune] ]);
+ *  motman->addMotion( SharedObject<YourMC>([arg1,...]) , autoprune [, priority ]);
  *  @endcode
  *  
  *  But if you want to do some more initializations not handled by the
@@ -47,7 +47,7 @@
  *  tmpvar->cmd1();
  *  tmpvar->cmd2();
  *  //...
- *  motman->addMotion(tmpvar [, ...]);
+ *  motman->addPrunableMotion(tmpvar [, ...]); //or addPersistentMotion(...)
  *  @endcode
  *
  *  Notice that tmpvar is of type SharedObject, but you're calling @c
@@ -124,14 +124,23 @@
 	//!@name MotionCommand Unsafe
 	//@{
 #ifdef PLATFORM_APERIOS
-	MC_ID addMotion(const SharedObjectBase& sm); //!< @b LOCKS @b MotionManager Creates a new MotionCommand, automatically sharing it between processes (there is some lag time here)
-	MC_ID addMotion(const SharedObjectBase& sm, float priority); //!< @b LOCKS @b MotionManager allows a quick way to set a priority level of a new MotionCommand
-	MC_ID addMotion(const SharedObjectBase& sm, bool autoprune); //!< @b LOCKS @b MotionManager allows a quick was to set the autoprune flag
-	MC_ID addMotion(const SharedObjectBase& sm, float priority, bool autoprune); //!< @b LOCKS @b MotionManager Call one of these to add a MotionCommand to the MotionManager, using the SharedObject class
+	//! @b LOCKS @b MotionManager adds a new motion (wrapped in a SharedObject) and marks that it should be automatically deleted when the MotionCommand::isAlive() returns false.
+	MC_ID addPrunableMotion(const SharedObjectBase& sm, float priority=kStdPriority) { return doAddMotion(sm,true,priority); }
+	//! @b LOCKS @b MotionManager adds a new motion (wrapped in a SharedObject) and marks that it should @e not be deleted, until removeMotion(MC_ID mcid) is called.
+	MC_ID addPersistentMotion(const SharedObjectBase& sm, float priority=kStdPriority) { return doAddMotion(sm,false,priority); }
 #endif //PLATFORM_APERIOS
 	void removeMotion(MC_ID mcid); //!< @b LOCKS @b MotionManager removes the specified MotionCommand
 	//@}
 
+	//!@name Deprecated
+#ifdef PLATFORM_APERIOS
+	MC_ID addMotion(const SharedObjectBase& sm) __attribute__((deprecated)); //!< deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises
+	MC_ID addMotion(const SharedObjectBase& sm, bool autoprune) __attribute__((deprecated)); //!< deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises
+	MC_ID addMotion(const SharedObjectBase& sm, float priority) __attribute__((deprecated)); //!< deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises
+	MC_ID addMotion(const SharedObjectBase& sm, float priority, bool autoprune) __attribute__((deprecated)); //!< deprecated, we're recommending users call either addPrunableMotion() or addPersistentMotion() so there are no surprises
+#endif //PLATFORM_APERIOS
+	//@}
+
 	//@{
 	void lock()    { MMlock.lock(_MMaccID); } //!< gets an exclusive lock on MotionManager - functions marked @b LOCKS @b MotionManager will cause (and require) this to happen automatically
 	bool trylock() { return MMlock.try_lock(_MMaccID); } //!< tries to get a lock without blocking
@@ -166,6 +175,11 @@
 	};
 
 protected:
+#ifdef PLATFORM_APERIOS
+	//!does the actual work of adding a motion
+	MC_ID doAddMotion(const SharedObjectBase& sm, bool autoprune, float priority);
+#endif
+	
 	//! used to request pids for a given joint
 	struct PIDUpdate {
 		//!constructor
@@ -246,9 +260,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.20 $
+ * $Revision: 1.23 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/10/18 23:10:26 $
  */
 
 #endif
Index: Motion/MotionSequenceMC.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/MotionSequenceMC.cc,v
retrieving revision 1.10
retrieving revision 1.15
diff -u -d -r1.10 -r1.15
--- Motion/MotionSequenceMC.cc	6 Jan 2004 03:19:29 -0000	1.10
+++ Motion/MotionSequenceMC.cc	14 Oct 2004 23:02:53 -0000	1.15
@@ -1,6 +1,7 @@
 #include "MotionSequenceMC.h"
 #include "Shared/get_time.h"
 #include "Shared/WorldState.h"
+#include "Shared/Config.h"
 #include <iostream>
 
 using std::cout;
@@ -67,20 +68,43 @@
 
 unsigned int MotionSequence::LoadBuffer(const char buf[], unsigned int len) {
 	unsigned int origlen=len;
-	if(strncmp("#MSq\n",buf,5)!=0) {
-		//		cout << "ERROR MotionSequence load corrupted - expected #MSq header" << endl;
+	if(strncmp("#MSq",buf,4)!=0) {
+		// we don't want to display an error here because we may be only testing file type,
+		// so it's up to the caller to decide if it's necessarily an error if the file isn't
+		// a motion sequence
+		//cout << "ERROR MotionSequence load corrupted - expected #MSq header" << endl;
 		return 0;
 	}
-	unsigned int linenum=2;
+	unsigned int linenum=1;
 	unsigned int lastOutputIdx=0;
 	while(len<=origlen && len>0) {
 		int written;
-		//		printf("%d %.9s\n",linenum+1,buf);
-		if(buf[0]=='#' || buf[0]=='\n') {
-			if(strncmp("#END\n",buf,5)==0)
-				return origlen-len;
-			else {
-				while(*buf++!='\n') {}
+		//printf("%d %.9s\n",linenum+1,buf);
+		if(buf[0]=='\r') {
+			buf++; len--;
+			if(buf[0]=='\n') {
+				buf++; len--;
+			}
+			linenum++;
+			continue;
+		}
+		if(buf[0]=='\n') {
+			buf++; len--;
+			linenum++;
+			continue;
+		}
+		if(buf[0]=='#') {
+			if(strncmp("#END\n",buf,5)==0 || strncmp("#END\r",buf,5)==0) {
+				return origlen-len+5;
+			} else if(strncmp("#END\r\n",buf,6)==0) {
+				return origlen-len+6;
+			} else {
+				while(len>0 && *buf!='\n' && *buf!='\r') {len--;buf++;}
+				if(*buf=='\n') { //in case of \r\n
+					buf++;
+					len--;
+				}
+				linenum++;
 				continue;
 			}
 		}
@@ -97,7 +121,11 @@
 		written=readWord(buf,&buf[len],arg2,arglen);
 		if(written!=0)
 			if(!ChkAdvance(written,&buf,&len,"*** ERROR MotionSequence load corrupted - line %d\n",linenum)) return 0;
-		for(;len>0 && *buf!='\n';buf++,len--) {}
+		for(;len>0 && *buf!='\n' && *buf!='\r';buf++,len--) {}
+		if(*buf=='\n') { //in case of \r\n
+			buf++;
+			len--;
+		}
 
 		if(strcasecmp(command,"delay")==0) {
 			char* used;
@@ -121,9 +149,9 @@
 			if(arg1[0]!='/')
 				f="/ms/data/motion/";
 			f+=arg1;
-			if(pose.LoadFile(f.c_str())!=0)
+			if(pose.LoadFile(f.c_str())!=0) {
 				setPose(pose);
-			else
+			} else
 				cout << "*** WARNING could not read file " << arg1 << " for load - line " << linenum << endl;
 		} else if(strcasecmp(command,"overlay")==0) {
 			PostureEngine pose;
@@ -228,6 +256,13 @@
 	cout << "SAVE-done!" << endl;
 }
 
+unsigned int MotionSequence::LoadFile(const char filename[]) {
+	return LoadSave::LoadFile(config->motion.makePath(filename).c_str());
+}
+unsigned int MotionSequence::SaveFile(const char filename[]) const {
+	return LoadSave::SaveFile(config->motion.makePath(filename).c_str());
+}
+
 void MotionSequence::setPlayTime(unsigned int x) {
 	playtime=x;
 	for(unsigned int i=0; i<NumOutputs; i++)
@@ -240,6 +275,8 @@
 		p_m.cmd=cmd;
 	} else { //add new keyframe
 		Move_idx_t x = newKeyFrame();
+		if(x==invalid_move) //ran out of memory - newKeyFrame should report error, we can silently die
+			return;
 		Move& cur=getKeyFrame(x);
 		Move& prev_m=getKeyFrame(prevs[i]); //it's important to refresh this - newKeyFrame may have invalidated p_m reference
 		cur.cmd=cmd;
@@ -347,28 +384,6 @@
 	}
 }
 
-bool MotionSequence::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg) {
-	if(res>0) {
-		*buf+=res;
-		*len-=res;
-		return true;
-	} else {
-		printf("%s",msg);
-		return false;
-	}
-}
-
-bool MotionSequence::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1) {
-	if(res>0) {
-		*buf+=res;
-		*len-=res;
-		return true;
-	} else {
-		printf(msg,arg1);
-		return false;
-	}
-}
-
 unsigned int MotionSequence::setNextFrameTime(Move_idx_t p[NumOutputs], Move_idx_t n[NumOutputs]) const {
 	unsigned int ans=-1U;
 	for(unsigned int i=0; i<NumOutputs; i++)
@@ -385,7 +400,7 @@
 	wrd[0]='\0';
 	unsigned int i;
 	//skip whitespace
-	for(;buf<bufend && isspace(*buf) && *buf!='\n';buf++) {}
+	for(;buf<bufend && isspace(*buf) && *buf!='\n' && *buf!='\r';buf++) {}
 	//store wrd
 	for(i=0; buf<bufend && !isspace(*buf); buf++)
 		if(i<wordlen-1)
@@ -420,8 +435,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.10 $
+ * $Revision: 1.15 $
  * $State: Exp $
- * $Date: 2004/01/06 03:19:29 $
+ * $Date: 2004/10/14 23:02:53 $
  */
 
Index: Motion/MotionSequenceMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/MotionSequenceMC.h,v
retrieving revision 1.12
retrieving revision 1.20
diff -u -d -r1.12 -r1.20
--- Motion/MotionSequenceMC.h	19 Feb 2004 23:08:09 -0000	1.12
+++ Motion/MotionSequenceMC.h	14 Oct 2004 19:24:46 -0000	1.20
@@ -44,21 +44,61 @@
  *  @see MotionSequence::SizeSmall, MotionSequence::SizeMedium, MotionSequence::SizeLarge, MotionSequence::SizeXLarge, 
  *  
  *  The file format used is as follows: ('<' and '>' are not meant literally)
- *  @verbatim
- *       First line: #MSq
- *  Zero or more of: delay <time-delta>              (moves playhead forward, in milliseconds)
- *               or: settime <time>                  (sets play time to specified value, in ms)
- *               or: <outputname> <value> [<weight>] (sets the specified output to the value - assumes 1 for weight)
- *               or: load <filename>                 (file is a posture, sets position)
- *               or: overlay <filename>              (file can be a posture or another motion sequence)
- *               or: degrees                         (following <value>s will be interpreted as degrees [default])
- *               or: radians                         (following <value>s will be interpreted as radians)
- *        Last line: #END
- *  @endverbatim
+ *  - First line: '<tt>#MSq</tt>'
+ *  - Followed by any series of:\n
+ *    - '<tt>delay </tt><i>time-delta</i>' - moves playhead forward, in milliseconds
+ *    - '<tt>settime </tt><i>time</i>' - sets play time to specified value, in ms
+ *    - '<i>outputname</i><tt> </tt><i>value</i><tt> </tt>[<i>weight</i>]' - sets the specified output to the value - assumes 1 for weight; you can view the list of valid joint names in the outputNames array within the RobotInfo extension namespace for your model.  (e.g. ERS210Info::outputNames[])
+ *    - '<tt>load </tt><i>filename</i>' - file is a posture, sets position
+ *    - '<tt>overlay </tt><i>filename</i>' - file can be a posture or another motion sequence
+ *    - '<tt>degrees</tt>' - following <i>value</i>s will be interpreted as degrees [default]
+ *    - '<tt>radians</tt>' - following <i>value</i>s will be interpreted as radians
+ *    - '<tt>#</tt><i>comment</i>' - a comment line
+ *  - Last line: '<tt>#END</tt>'
+ *  
  *  After loading a motion sequence, the playtime is left at the end.
- *  This is to make it easy to append/overlay motion sequences
+ *  This is to make it easy to append/overlay motion sequences.
+ *  However, the playhead will be reset to the beginning on the first
+ *  call to updateOutputs() if isPlaying() returns true.
+ *
+ *  You can also create a MotionSequence dynamically at run time:
+ *  \code
+ *  //This code sample will stand up, point the head forward and up 0.1 radians,
+ *  //and then autoprune
+ *
+ *  //First declare the MotionSequence itself:
+ *  SharedObject< MotionSequenceMC<MotionSequence::SizeSmall> > stand;
+ *
+ *  //Over the course of 700 milliseconds, go to standing posture:
+ *  standSit->setPlayTime(700);
+ *  standSit->setPose(PostureEngine("/ms/data/motion/stand.pos"));
+ *
+ *  //Then take another 700 milliseconds to straighten out the head:
+ *  standSit->setPlayTime(700);
+ *  //We'll set joints individually this time, instead of loading a posture file:
+ *  standSit->setOutputCmd(HeadOffset+PanOffset,0);
+ *  standSit->setOutputCmd(HeadOffset+RollOffset,0);
+ *  standSit->setOutputCmd(HeadOffset+TiltOffset,0.1); //look up .1 radians
+ *
+ *  //Add to MotionManager:
+ *  motman->addMotion(standSit);
+ *  //Playback will now begin automatically, and region deallocated when done
+ *  \endcode
  *  
- *  Lines beginning with '#' are ignored.  Output names are defined in RobotInfo.h, RobotInfo::outputNames.
+ *  By default, #playing is true.  Thus, when you add a MotionSequence
+ *  to the MotionManager, it will begin executing automatically.  If
+ *  you do \e not want this behavior, simply call pause() before
+ *  adding the sequence.
+ *
+ *  When the sequence reaches the end, isAlive() will return false.
+ *  By default, the motion sequence will autoprune itself from the
+ *  MotionManager.  However, you can either pass \c false to
+ *  MotionManager::addMotion(), or call setAutoPrune(false).
+ *  
+ *  Lines beginning with '#' are ignored as comments.  Be aware if you
+ *  load the file and then save it again, these comments will be lost.
+ *  
+ *  @see PostureEngine for information on the posture files
  */
 class MotionSequence : public MotionCommand, public LoadSave {
 public:
@@ -86,6 +126,8 @@
 	virtual unsigned int getBinSize() const; //!< inherited, returns the size used to save the sequence
 	virtual unsigned int LoadBuffer(const char buf[], unsigned int len); //!< inherited, doesn't clear before loading - call clear yourself if you want to reset, otherwise it will overlay.  Leaves playtime at end of load.
 	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const; //!< inherited, saves the motion sequence - will save a flat file - doesn't remember references to other files which were loaded
+	virtual unsigned int LoadFile(const char filename[]); //!< inherited, doesn't clear before loading - call clear yourself if you want to reset, otherwise it will overlay.  Leaves playtime at end of load.
+	virtual unsigned int SaveFile(const char filename[]) const; //!< inherited, saves the motion sequence - will save a flat file - doesn't remember references to other files which were loaded
 	void setSaveDegrees() { loadSaveMode=M_PI/180; }       //!< will store angles as degrees on future saves
 	bool isSaveDegrees() const { return loadSaveMode!=1; } //!< returns true if will store angles as degrees on future saves
 	void setSaveRadians() { loadSaveMode=1; }              //!< will store angles as radians on future saves
@@ -159,12 +201,6 @@
 	//!Sets prev and next to the appropriate values for the given time and output index
 	virtual void setRange(unsigned int t,Move_idx_t& prev, Move_idx_t& next) const=0;
 
-	//!used by LoadBuffer()/SaveBuffer(), checks to see if the amount read/written (@a res) is nonzero, increments @a buf, decrements @a len, or displays @a msg if @a is zero
-	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg);
-
-	//!used by LoadBuffer()/SaveBuffer(), checks to see if the amount read/written (@a res) is nonzero, increments @a buf, decrements @a len, or displays @a msg with @a arg1 if @a is zero
-	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1);
-
 	//!sets playtime to next time for which any output has a keyframe, -1 if none exists
 	unsigned int setNextFrameTime(Move_idx_t p[NumOutputs], Move_idx_t n[NumOutputs]) const;
 	
@@ -185,9 +221,19 @@
 class MotionSequenceMC : public MotionSequence {
 public:
 	//!constructor
-	MotionSequenceMC() : MotionSequence(), moves() {clear();}
+	MotionSequenceMC()
+		: MotionSequence(), moves()
+	{
+		clear();
+	}
 	//!constructor, loads from a file and then resets the playtime to beginning and begins to play
-	explicit MotionSequenceMC(const char* filename) : MotionSequence(), moves() {clear();LoadFile(filename);setPlayTime(1);}
+	explicit MotionSequenceMC(const char* filename)
+		: MotionSequence(), moves()
+	{
+		clear();
+		LoadFile(filename);
+		setPlayTime(1);
+	}
 	//!destructor
 	virtual ~MotionSequenceMC() {}
 
@@ -268,7 +314,12 @@
 
 	virtual Move& getKeyFrame(Move_idx_t x) { return moves[x]; }
 	virtual const Move& getKeyFrame(Move_idx_t x) const { return moves[x]; }
-	virtual Move_idx_t newKeyFrame() { return moves.new_front(); }
+	virtual Move_idx_t newKeyFrame() {
+		Move_idx_t i=moves.new_front();
+		if(i==invalid_move)
+			serr->printf("ERROR: MotionSequenceMC %d has run out of memory\n",getID());
+		return i;
+	}
 	virtual void eraseKeyFrame(Move_idx_t x) { moves.erase(x); }
 	void setRange(unsigned int t,Move_idx_t& prev, Move_idx_t& next) const {
 		if(next!=invalid_move && moves[next].starttime<=t) {
@@ -276,11 +327,11 @@
 				prev=next;
 				next=moves[prev].next;
 			} while(next!=invalid_move && moves[next].starttime<=t);
-		} else if(t<moves[prev].starttime) {
-			do {
+		} else {
+			while(moves[prev].prev!=invalid_move && t<moves[prev].starttime) {
 				next=prev;
 				prev=moves[next].prev;
-			} while(t<moves[prev].starttime);
+			} 
 		}
 	}
 };
@@ -291,9 +342,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.20 $
  * $State: Exp $
- * $Date: 2004/02/19 23:08:09 $
+ * $Date: 2004/10/14 19:24:46 $
  */
 
 #endif
Index: Motion/OldHeadPointerMC.cc
===================================================================
RCS file: Motion/OldHeadPointerMC.cc
diff -N Motion/OldHeadPointerMC.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/OldHeadPointerMC.cc	14 Oct 2004 20:23:50 -0000	1.1
@@ -0,0 +1,185 @@
+#include "OldHeadPointerMC.h"
+#include "Shared/debuget.h"
+#include "Shared/WorldState.h"
+#include "MotionManager.h"
+#include <math.h>
+#include "Shared/Config.h"
+
+OldHeadPointerMC::OldHeadPointerMC() :
+  MotionCommand(), dirty(true), active(true), targetReached(false) {
+  setWeight(1);
+  defaultMaxSpeed();
+  for(unsigned int i=0; i<NumHeadJoints; i++) {
+    headModes[i]=BodyRelative;
+    headTargets[i]=0;
+    headCmds[i].value=state->outputs[HeadOffset+i];
+  }
+}
+
+void OldHeadPointerMC::setJoints(double tilt, double pan, double roll) {
+	setJointValue(TiltOffset,tilt);
+	setJointValue(PanOffset,pan);
+	setJointValue(RollOffset,roll);
+}
+
+void OldHeadPointerMC::setWeight(double w) {
+  for(unsigned int x=0; x<NumHeadJoints; x++)
+    headCmds[x].weight=w;
+  dirty=true; targetReached=false;
+}
+
+void OldHeadPointerMC::defaultMaxSpeed() {
+  maxSpeed[TiltOffset]=config->motion.max_head_tilt_speed*FrameTime/1000;
+  maxSpeed[PanOffset]=config->motion.max_head_pan_speed*FrameTime/1000;
+  maxSpeed[RollOffset]=config->motion.max_head_roll_speed*FrameTime/1000;
+}
+
+void OldHeadPointerMC::setMode(CoordFrame_t m, bool conv) {
+  for(unsigned int x=0; x<NumHeadJoints; x++)
+    setJointMode((RobotInfo::TPROffset_t)x,m,conv);
+}
+
+void OldHeadPointerMC::setJointMode(RobotInfo::TPROffset_t i, CoordFrame_t m, bool conv) {
+  if(conv)
+    headTargets[i]=OldHeadPointerMC::convert(i,headTargets[i],headModes[i],m);
+  headModes[i]=m;
+  dirty=true; targetReached=false;
+}
+
+int OldHeadPointerMC::updateOutputs() {
+  int tmp=isDirty();
+  if(tmp) {
+    dirty=false;
+    for(unsigned int i=0; i<NumHeadJoints; i++) {
+      float value;
+      if(headModes[i]!=BodyRelative) {
+	value=convToBodyRelative((RobotInfo::TPROffset_t)i,headTargets[i],headModes[i]);
+	dirty=true;
+      } else
+	value=headTargets[i];
+      if(maxSpeed[i]<=0)
+	headCmds[i].value=value;
+      if(value==headCmds[i].value) {
+	motman->setOutput(this,i+HeadOffset,headCmds[i]);
+      } else { // we may be trying to exceeded maxSpeed
+	unsigned int f=0;
+	while(value>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
+	  headCmds[i].value+=maxSpeed[i];
+	  motman->setOutput(this,i+HeadOffset,headCmds[i],f);
+	  f++;
+	}
+	while(value<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
+	  headCmds[i].value-=maxSpeed[i];
+	  motman->setOutput(this,i+HeadOffset,headCmds[i],f);
+	  f++;
+	}
+	if(f<NumFrames) { //we reached target value, fill in rest of frames
+	  headCmds[i].value=value;
+	  for(;f<NumFrames;f++)
+	    motman->setOutput(this,i+HeadOffset,headCmds[i],f);
+	} else // we didn't reach target value, still dirty
+	  dirty=true;
+      }
+    }
+    float dist=0;
+    for(unsigned int i=0; i<NumHeadJoints; i++) {
+      float diff=(state->outputs[HeadOffset+i]-headTargets[i]);
+      dist+=diff*diff;
+    }
+    if(dist<0.05*0.05 && !targetReached) {
+      postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
+      targetReached=true;
+    }
+  }
+  return tmp;
+}
+
+const OutputCmd& OldHeadPointerMC::getOutputCmd(unsigned int i) {
+  i-=HeadOffset;
+  if(i<NumHeadJoints && getActive())
+    return headCmds[i];
+  else
+    return OutputCmd::unused;
+}
+
+/*! @todo this is perhaps a bit amateurish - could be more accurate */
+double OldHeadPointerMC::convToBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const {
+  switch(mode) {
+  default:
+    ASSERT(false,"Passed bad mode "<<mode);
+  case BodyRelative:
+    return v;
+  case GravityRelative: {
+    double bacc=state->sensors[BAccelOffset];
+    double lacc=state->sensors[LAccelOffset];
+    double dacc=state->sensors[DAccelOffset];
+    switch(i) {
+    case TiltOffset:
+      return v+atan2(bacc,sqrt(dacc*dacc+lacc*lacc));
+    case PanOffset:
+      return v;
+    case RollOffset: //==NodOffset
+      if(state->robotDesign&WorldState::ERS7Mask) {
+	float pans=sin(state->outputs[HeadOffset+PanOffset]);
+	float panc=cos(state->outputs[HeadOffset+PanOffset]);
+	float ans=v;
+	ans+=atan2(bacc*panc-lacc*pans,sqrt(dacc*dacc+lacc*lacc*panc*panc+bacc*bacc*pans*pans));
+	ans-=panc*state->outputs[HeadOffset+TiltOffset];
+	return ans;
+      } else
+	return v+atan2(-lacc,sqrt(dacc*dacc+bacc*bacc));
+    default:
+      ASSERT(false,"Passed bad offset "<<i<<" (use RobotInfo::TPROffset_t!)");
+      return v;
+    }
+  }
+  }
+}
+
+/*! @todo this is perhaps a bit amateurish - could be more accurate */
+double OldHeadPointerMC::convFromBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const {
+  switch(mode) {
+  default:
+    ASSERT(false,"Passed bad mode "<<mode);
+  case BodyRelative:
+    return v;
+  case GravityRelative: {
+    double bacc=state->sensors[BAccelOffset];
+    double lacc=state->sensors[LAccelOffset];
+    double dacc=state->sensors[DAccelOffset];
+    switch(i) {
+    case TiltOffset:
+      return v-atan2(bacc,sqrt(dacc*dacc+lacc*lacc));
+    case PanOffset:
+      return v;
+    case RollOffset: //==NodOffset
+      if(state->robotDesign&WorldState::ERS7Mask) {
+	float pans=sin(state->outputs[HeadOffset+PanOffset]);
+	float panc=cos(state->outputs[HeadOffset+PanOffset]);
+	float ans=v;
+	ans-=atan2(bacc*panc-lacc*pans,sqrt(dacc*dacc+lacc*lacc*panc*panc+bacc*bacc*pans*pans));
+	ans+=panc*state->outputs[HeadOffset+TiltOffset];
+	return ans;
+      } else
+	return v-atan2(-lacc,sqrt(dacc*dacc+bacc*bacc));
+    default:
+      ASSERT(false,"Passed bad offset "<<i<<" (use RobotInfo::TPROffset_t!)");
+      return v;
+    }
+  }
+  }
+}
+
+
+/*! @file
+ * @brief Implements OldHeadPointerMC, a class for various ways to control where the head is looking
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/10/14 20:23:50 $
+ */
+
+
Index: Motion/OldHeadPointerMC.h
===================================================================
RCS file: Motion/OldHeadPointerMC.h
diff -N Motion/OldHeadPointerMC.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/OldHeadPointerMC.h	14 Oct 2004 20:23:50 -0000	1.1
@@ -0,0 +1,126 @@
+//-*-c++-*-
+#ifndef INCLUDED_OldHeadPointerMC_h
+#define INCLUDED_OldHeadPointerMC_h
+
+#include "MotionCommand.h"
+#include "OutputCmd.h"
+#include "Shared/RobotInfo.h"
+
+//! This class gives some quick and easy functions to point the head at things
+class OldHeadPointerMC : public MotionCommand {
+public:
+  //! constructor, defaults to active, BodyRelative, all joints at 0
+  OldHeadPointerMC();
+
+  //! destructor
+  virtual ~OldHeadPointerMC() {}
+
+  //! Various modes the head can be in.  In the future may want to add ability to explicitly track an object or point in the world model
+  enum CoordFrame_t {
+    BodyRelative,    //!<holds neck at a specified position, like a PostureEngine, but neck specific
+    GravityRelative  //!<uses accelerometers to keep a level head, doesn't apply for pan joint, but in future could use localization for pan
+  };
+
+  void   setWeight(double w);                               //!< sets the weight values for all the neck joints
+
+  //! set a specific head joint weight, pass one of RobotInfo::TPROffset_t, not a full offset!
+  void setWeight(RobotInfo::TPROffset_t i, double weight) {
+    dirty=true; targetReached=false; headCmds[i].weight=weight; }
+
+  void   setActive(bool a) { active=a; } //!< sets #active flag; see isDirty()
+  bool   getActive() const { return active; } //!< returns #active flag, see isDirty()
+
+  //! sets #maxSpeed to 0 (no maximum)
+  void noMaxSpeed() { for(unsigned int i=0; i<NumHeadJoints; i++) maxSpeed[i]=0; }
+
+  void defaultMaxSpeed(); //!< restores #maxSpeed to default settings from Config::Motion_Config
+
+  void setMaxSpeed(TPROffset_t i, float x) { maxSpeed[i]=x*FrameTime/1000; } //!< sets #maxSpeed in rad/sec
+  float getMaxSpeed(TPROffset_t i) { return maxSpeed[i]*1000/FrameTime; } //!< returns #maxSpeed in rad/sec
+
+  //! converts a value @a v in @a srcmode to a value in @a tgtmode that would leave the joint angle for joint @a i constant (you probably won't need to call this directly)
+  double convert(RobotInfo::TPROffset_t i, double v, CoordFrame_t srcmode, CoordFrame_t tgtmode) const {
+    return (srcmode==tgtmode)?v:convFromBodyRelative(i,convToBodyRelative(i, v, srcmode),tgtmode);
+  }
+
+  //!Note that none of these are @c virtual, so you don't have to checkout to use them, you @e should be able to use MotionManager::peekMotion()
+  //!@name Joint Accessors
+
+  //! Directly sets the neck values (radians), uses current mode
+  void setJoints(double tilt, double pan, double roll);
+
+  //! sets all the joints to the given mode, will convert the values to the new mode if @a convert is true
+  void setMode(CoordFrame_t m, bool convert=true); 
+
+    //! sets a specific head joint's mode; will convert from previous mode's value to next mode's value if convert is true.  Pass one of RobotInfo::TPROffset_t, not a full offset!
+  void setJointMode(RobotInfo::TPROffset_t i, CoordFrame_t m, bool convert=true);
+
+  //! set a specific head joint's value (in radians, for whatever mode it's in), pass one of RobotInfo::TPROffset_t, not a full offset!
+  void setJointValue(RobotInfo::TPROffset_t i, double value)
+	{ dirty=true; targetReached=false; headTargets[i]=(headModes[i]==BodyRelative)?clipAngularRange(i+HeadOffset,value):value; }
+
+  //! set a specific head joint (in radians), pass one of RobotInfo::TPROffset_t, not a full offset!
+  void setJointValueAndMode(RobotInfo::TPROffset_t i, double value, CoordFrame_t m)
+  { dirty=true; targetReached=false; headTargets[i]=(m==BodyRelative)?clipAngularRange(i+HeadOffset,value):value; headModes[i]=m; }
+
+  //! set a specific head joint (in radians) auto converting @a value from mode @a m to the current mode, pass one of RobotInfo::TPROffset_t, not a full offset!
+  void setJointValueFromMode(RobotInfo::TPROffset_t i, double value, CoordFrame_t m)
+  { dirty=true; targetReached=false; headTargets[i]=convert(i,value,m,headModes[i]); }
+
+  //! returns the current mode for joint @a i (use RobotInfo::TPROffset_t, not global offset)
+  CoordFrame_t getJointMode(RobotInfo::TPROffset_t i) const { return headModes[i]; }
+
+  //! returns the target value (relative to the current mode) of joint @a i.  Use getOutputCmd() if you want to know the current @b commanded joint value; To get the current joint @b position, look in WorldState
+  double getJointValue(RobotInfo::TPROffset_t i) const { return headTargets[i]; }
+  //@}
+
+
+  //!@name Inherited:
+  virtual int updateOutputs(); //!< Updates where the head is looking
+  virtual const OutputCmd& getOutputCmd(unsigned int i);  //!< returns one of the #headJoints entries or ::unusedJoint if not a head joint
+  virtual int isDirty() { return ((dirty || !targetReached) && active)?1:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
+  virtual int isAlive() { return true; }
+  virtual void DoStart() { MotionCommand::DoStart(); dirty=true; targetReached=false; }
+  //@}
+
+ protected:
+  double convToBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const;   //!< converts to a body relative measurement for joint @a i
+  double convFromBodyRelative(TPROffset_t i, double v, CoordFrame_t mode) const; //!< converts from a body relative measurement for joint @a i
+	static float normalizeAngle(float x) { return x-rint(x/(2*M_PI))*(2*M_PI); } //!< puts x in the range (-pi,pi)
+	//! if @a x is outside of the range of joint @a i, it is set to either the min or the max, whichever is closer
+	static float clipAngularRange(unsigned int i, float x) {
+		float min=outputRanges[i][MinRange];
+		float max=outputRanges[i][MaxRange];
+		if(x<min || x>max) {
+			float mn_dist=fabs(normalizeAngle(min-x));
+			float mx_dist=fabs(normalizeAngle(max-x));
+			if(mn_dist<mx_dist)
+				return min;
+			else
+				return max;
+		} else
+			return x;
+	}
+
+  bool dirty;                            //!< true if a change has been made since last call to updateJointCmds()
+  bool active;                           //!< set by accessor functions, defaults to true
+  bool targetReached;                  //!< false if the head is still moving towards its target
+  OutputCmd headCmds[NumHeadJoints] ;  //!< stores the last values we sent from updateOutputs
+  float headTargets[NumHeadJoints];       //!< stores the target value of each joint, relative to #headModes
+  CoordFrame_t headModes[NumHeadJoints]; //!< stores the current mode of each joint, for instance so tilt can be GravityRelative while pan is static
+  float maxSpeed[NumHeadJoints];         //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
+};
+
+/*! @file
+ * @brief Describes OldHeadPointerMC, a class for various ways to control where the head is looking
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/10/14 20:23:50 $
+ */
+
+#endif
+
Index: Motion/OldKinematics.cc
===================================================================
RCS file: Motion/OldKinematics.cc
diff -N Motion/OldKinematics.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/OldKinematics.cc	5 Aug 2004 20:29:04 -0000	1.1
@@ -0,0 +1,611 @@
+//This class is ported from Carnegie Mellon's 2001 Robosoccer entry, and falls under their license:
+/*=========================================================================
+    CMPack'02 Source Code Release for OPEN-R SDK v1.0
+    Copyright (C) 2002 Multirobot Lab [Project Head: Manuela Veloso]
+    School of Computer Science, Carnegie Mellon University
+  -------------------------------------------------------------------------
+    This software is distributed under the GNU General Public License,
+    version 2.  If you do not have a copy of this licence, visit
+    www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
+    Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
+    in the hope that it will be useful, but WITHOUT ANY WARRANTY,
+    including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  -------------------------------------------------------------------------
+    Additionally licensed to Sony Corporation under the following terms:
+
+    This software is provided by the copyright holders AS IS and any
+    express or implied warranties, including, but not limited to, the
+    implied warranties of merchantability and fitness for a particular
+    purpose are disclaimed.  In no event shall authors be liable for
+    any direct, indirect, incidental, special, exemplary, or consequential
+    damages (including, but not limited to, procurement of substitute
+    goods or services; loss of use, data, or profits; or business
+    interruption) however caused and on any theory of liability, whether
+    in contract, strict liability, or tort (including negligence or
+    otherwise) arising in any way out of the use of this software, even if
+    advised of the possibility of such damage.
+  =========================================================================
+*/
+
+#ifdef PLATFORM_LINUX
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+#include <math.h>
+
+#include "OldKinematics.h"
+//#include "Wireless/Socket.h"
+#include "Shared/ERS7Info.h"
+
+// #define DEBUG
+
+#ifdef TGT_ERS7
+// ERS-7 Leg Parameters
+const vector3d f_body_to_shoulder       ( 65.00, 62.50,   0.00);
+const vector3d f_leg_shoulder_to_knee   (  9.00,  4.70, -69.50);
+const vector3d f_leg_knee_to_ball       (-11.24,  0.00, -76.07);
+
+const vector3d h_body_to_shoulder       (-65.00, 62.50,   0.00);
+const vector3d h_leg_shoulder_to_knee   ( -9.00,  4.70, -69.50);
+const vector3d h_leg_knee_to_ball       ( 19.80,  0.00, -76.90);
+#else
+// ERS-210/220 Leg Parameters
+const vector3d f_body_to_shoulder       ( 59.50, 59.20,   0.00);
+const vector3d f_leg_shoulder_to_knee   ( 12.80,  0.50, -64.00);
+const vector3d f_leg_knee_to_ball       (-18.88,  0.00, -66.00);
+
+const vector3d h_body_to_shoulder       (-59.50, 59.20,   0.00);
+const vector3d h_leg_shoulder_to_knee   (-12.80,  0.50, -64.00);
+const vector3d h_leg_knee_to_ball       ( 29.36,  0.00, -70.88);
+/*
+	knee_to_ball was found to be possible to compute from diagrams, 4/11/04 ejt
+	previous values by original author are as follows:
+  18 : measured
+  67.23 = sqrt(69.6^2 - 18^2)
+  74.87 = sqrt(77^2 - 18^2)
+  0.2616 = asin(18 / 69.6)
+  0.2316 = asin(18 / 77)
+	const vector3d f_leg_knee_to_ball       (-18.00,  0.00, -67.23);
+	const vector3d h_leg_knee_to_ball       ( 18.00,  0.00, -74.87);
+*/
+#endif
+
+/* ERS-110
+const vector3d f_body_to_shoulder       ( 44.85, 26.50,   0.00);
+const vector3d f_leg_shoulder_to_knee   ( 13.00,  5.50, -61.00);
+const vector3d f_leg_knee_to_ball       ( -9.50,  1.06, -58.00); // ??
+
+const vector3d h_body_to_shoulder       (-44.85, 26.50,   0.00);
+const vector3d h_leg_shoulder_to_knee   (-13.00,  5.50, -61.00);
+const vector3d h_leg_knee_to_ball       ( 19.00,  1.06, -69.00); // ??
+*/
+
+#ifdef PLATFORM_LINUX
+void print(double *angles,vector3d pos)
+{
+  printf("A(%7.4f,%7.4f,%7.4f) P(%7.2f,%7.2f,%7.2f)\n",
+	 angles[0],angles[1],angles[2],
+	 pos.x,pos.y,pos.z);
+}
+#endif
+
+
+const vector3d f_upper = f_leg_shoulder_to_knee;
+const vector3d f_lower = f_leg_knee_to_ball;
+const vector3d h_upper = h_leg_shoulder_to_knee;
+const vector3d h_lower = h_leg_knee_to_ball;
+
+//==== Globals ====//
+#ifdef PLATFORM_LINUX
+int g_leg;
+vector3d g_target;
+#endif
+
+static int errors;
+
+void KinClearErrors()
+{
+  errors = 0;
+}
+
+int KinGetErrors()
+{
+  return(errors);
+}
+
+double GetTrigAngle(double a,double b,double d,double mn,double mx,bool add)
+// Analytic solution to a*sin(x) + b*cos(x) = d
+{
+  double theta;
+  double t,f,c;
+  int err;
+
+  f = d / sqrt(a*a + b*b);
+  err = 0;
+
+  if(fabs(f) > 1.0){
+#ifdef PLATFORM_LINUX
+    /*
+    printf("Out of range (distance=%g) leg=%d target=(%g,%g,%g)\n",f,
+           g_leg,g_target.x,g_target.y,g_target.z);
+    */
+#endif
+    f = (f > 0.0)? 1.0 : -1.0;
+    err = 1;
+  }
+
+  t = atan2(a,b);
+  c = acos(f);
+
+  theta = add? (t + c) : (t - c);
+
+  if(theta < mn){
+#ifdef PLATFORM_LINUX
+    /*
+    printf("Out of range (angle to small) leg=%d target=(%g,%g,%g)\n",
+           g_leg,g_target.x,g_target.y,g_target.z);
+    */
+#endif
+    errors++;
+    return(mn);
+  }else if(theta > mx){
+#ifdef PLATFORM_LINUX
+    /*
+    printf("Out of range (angle to large) leg=%d target=(%g,%g,%g)\n",
+           g_leg,g_target.x,g_target.y,g_target.z);
+    */
+#endif
+    errors++;
+    return(mx);
+  }else{
+    errors += err;
+    return(theta);
+  }
+}
+
+/*
+Angle Limits:
+           ===Software====  ==Mechanical===
+  Rotator  [-117.0, 117.0]  [-120.0, 120.0]
+  Shoulder [ -11.0,  97.0]  [ -14.0, 100.0]
+  Knee     [ -27.0, 147.0]  [ -30.0, 150.0]
+*/
+
+const double rotator_min  = RAD(-117.0);
+const double rotator_max  = RAD( 117.0);
+const double shoulder_min = RAD( -11.0);
+const double shoulder_max = RAD(  97.0);
+const double knee_max     = RAD( 147.0);
+const double knee_min     = RAD( -27.0);
+
+const double rotator_kmin  = RAD(-90.0);
+const double rotator_kmax  = RAD( 90.0);
+const double shoulder_kmin = shoulder_min;
+const double shoulder_kmax = RAD( 90.0);
+const double knee_kmax     = knee_max;
+const double f_knee_kmin   = 0.2616;
+const double h_knee_kmin   = 0.2316;
+
+const double tail_min = RAD(-22);
+const double tail_max = RAD( 22);
+
+const double head_tilt_min = RAD(-88.5);
+const double head_tilt_max = RAD( 43.0);
+const double head_pan_min  = RAD(-89.6);
+const double head_pan_max  = RAD( 89.6);
+const double head_roll_min = RAD(-29.0);
+const double head_roll_max = RAD( 29.0);
+
+
+void GetLegAngles(double *angles,vector3d target,int leg)
+{
+  vector3d targ,pos;
+  double knee,shoulder,rotator;
+  double a,b,d,dist;
+  bool front = leg < 2;
+
+#ifdef PLATFORM_LINUX
+  g_leg    = leg;
+  g_target = target;
+  // printf("GLA: target=(%g,%g,%g)\n",target.x,target.y,target.z);
+#endif
+
+  knee = shoulder = rotator = 0.0;
+
+  if(leg % 2) target.y = -target.y;
+
+  if(front){
+    targ = target - f_body_to_shoulder;
+    dist = targ.sqlength();
+
+    // Calculate knee angle
+    a = -2*(f_upper.x*f_lower.z - f_upper.z*f_lower.x);
+    b =  2*(f_upper.x*f_lower.x + f_upper.z*f_lower.z);
+    d = (dist - f_upper.sqlength() - f_lower.sqlength() - 2*f_upper.y*f_lower.y);
+    knee = GetTrigAngle(a,b,d,f_knee_kmin,knee_kmax,true);
+
+    // Calculate shoulder angle
+    pos = f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-knee);
+    shoulder = GetTrigAngle(-pos.z,pos.y,targ.y,shoulder_kmin,shoulder_kmax,false);
+
+    // Calculate rotator angle
+    // pos = pos.rotate_x(shoulder);
+    pos.z = sin(shoulder)*pos.y + cos(shoulder)*pos.z;
+    rotator = GetTrigAngle(-pos.z,pos.x,targ.x,rotator_min,rotator_max,target.z > 0.0);
+
+#ifdef DEBUG
+    // Test
+		//    pos = (f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-knee))
+		//           .rotate_x(shoulder).rotate_y(-rotator);
+		//    printf("D(%f,%f,%f)\n",targ.x - pos.x,targ.y - pos.y,targ.z - pos.z);
+#endif
+  }else{
+    targ = target - h_body_to_shoulder;
+    dist = targ.sqlength();
+
+    // Calculate knee angle
+    a = 2*(h_upper.x*h_lower.z - h_upper.z*h_lower.x);
+    b = 2*(h_upper.x*h_lower.x + h_upper.z*h_lower.z);
+    d = (dist - h_upper.sqlength() - h_lower.sqlength() - 2*h_upper.y*h_lower.y);
+    knee = GetTrigAngle(a,b,d,h_knee_kmin,knee_kmax,true);
+
+    // Calculate shoulder angle
+    pos = h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y(knee);
+    shoulder = GetTrigAngle(-pos.z,pos.y,targ.y,shoulder_kmin,shoulder_kmax,false);
+
+    // Calculate rotator angle
+    pos.z = sin(shoulder)*pos.y + cos(shoulder)*pos.z;
+    rotator = GetTrigAngle(-pos.z,-pos.x,-targ.x,rotator_min,rotator_max,target.z > 0.0);
+
+    /*
+    if(fabs(theta - rotator) > 0.01){
+      printf("ERROR(%f - %f = %f)\n",theta,rotator,theta - rotator);
+    }
+    */
+
+#ifdef DEBUG
+    // Test
+		//    pos = (h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y(angles[2]))
+		//           .rotate_x(angles[1]).rotate_y(angles[0]);
+		//    printf("D(%f,%f,%f)\n",targ.x - pos.x,targ.y - pos.y,targ.z - pos.z);
+#endif
+  }
+
+  angles[0] = rotator;
+  angles[1] = shoulder;
+  angles[2] = knee;
+}
+
+void GetLegAngles(double *angles,vector3d target[4],
+                  double body_angle,double body_height)
+{
+  vector3d p;
+  int i;
+
+  for(i=0; i<4; i++){
+    p = target[i];
+    p.z -= body_height;
+    p = p.rotate_y(-body_angle);
+    GetLegAngles(angles + 3*i,p,i);
+  }
+}
+
+void GetLegAngles(double *angles,vector3d target[4],BodyPosition &bp)
+{
+  vector3d p;
+  int i;
+
+  for(i=0; i<4; i++){
+    p = (target[i] - bp.loc).rotate_z(bp.angle.z).rotate_y(-bp.angle.y);
+    GetLegAngles(angles + 3*i,p,i);
+  }
+}
+
+void GetLegAngles(double *angles,vector3d target,BodyPosition &bp,int leg)
+{
+  vector3d p;
+
+  p = (target - bp.loc).rotate_z(bp.angle.z).rotate_y(-bp.angle.y);
+  GetLegAngles(angles,p,leg);
+}
+
+
+void GetLegPosition(vector3d& p, const double* ang, int leg)
+{
+	if(leg < 2){
+		p = f_body_to_shoulder +
+			(f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-ang[2]))
+			.rotate_x(ang[1]).rotate_y(-ang[0]);
+	}else{
+		p = h_body_to_shoulder +
+			(h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y( ang[2]))
+			.rotate_x(ang[1]).rotate_y( ang[0]);
+	}
+	
+	if(leg % 2)
+		p.y = -p.y;
+}
+void GetLegPosition(vector3d& p, const double* ang, BodyPosition &bp,int leg)
+{
+	GetLegPosition(p,ang,leg);
+	p=p.rotate_y(bp.angle.y).rotate_z(-bp.angle.z)+bp.loc;
+}
+
+
+void GetBodyLocation(vector3d &ball,vector3d &toe,const double *ang,int leg)
+// project various parts of foot that could touch by given joint angles
+{
+  if(leg < 2){
+    ball = f_body_to_shoulder +
+           (f_leg_shoulder_to_knee + f_leg_knee_to_ball.rotate_y(-ang[2]))
+           .rotate_x(ang[1]).rotate_y(-ang[0]);
+  }else{
+    ball = h_body_to_shoulder +
+           (h_leg_shoulder_to_knee + h_leg_knee_to_ball.rotate_y( ang[2]))
+           .rotate_x(ang[1]).rotate_y( ang[0]);
+  }
+
+  // TODO: toes
+  toe = ball;
+
+  if(leg % 2){
+    ball.y = -ball.y;
+    toe.y = -toe.y;
+  }
+}
+
+#ifdef TGT_ERS7
+//use the current setting for tilt joint, determine nod joint
+bool getNodAndPan(double *angles,vector3d target) {
+	target=target.rotate_y(angles[0]);
+
+	double dx=target.x-neck_to_nod.x;
+	double dy=target.y-neck_to_nod.y;
+	double dz=target.z-neck_to_nod.z;
+	double elv=atan2(dz,hypot(dx,dy)); //angle from xy plane at nod joint to target position
+	double camAng=atan2(nod_to_camera.z,nod_to_camera.x); //angle from xy plane at nod joint to actual camera position
+	double tgtDist=sqrt(dx*dx+dy*dy+dz*dz);
+	double camDist=hypot(nod_to_camera.x,nod_to_camera.z);
+
+	if(camDist>=tgtDist) {
+		for(unsigned int i=0; i<3; i++)
+			angles[i]=0;
+		return false;
+	}
+	double angle_base_target_camera=asin(camDist*sin(-camAng)/tgtDist);
+	angles[1]=atan2(target.y,target.x);
+	angles[2]=elv-2*camAng-angle_base_target_camera;
+
+	//sout->printf("elv=%g camAng=%g dx=%g dy=%g dz=%g abtc=%g nod=%g tilt=%g\n",elv,camAng,dx,dy,dz,angle_base_target_camera,angles[2],angles[0]);
+
+	return true;
+}
+#endif
+
+
+void GetHeadAngles(double *angles,vector3d target,
+                   double body_angle,double body_height)
+{
+#ifdef TGT_ERS7
+	//***********************************************
+	//******************** ERS-7 ********************
+	//***********************************************
+	if(!finite(angles[0]))
+		angles[0]=0;
+  vector3d neck = body_to_neck.rotate_y(body_angle);
+  target.z -= body_height + neck.z;
+
+	//try using just the nod joint...
+	if(!getNodAndPan(angles,target))
+		return;
+
+	//we could consider ourselves done if only using nod and pan, but
+	//but should use tilt too if out of range of nod
+
+	//if we can't pan far enough, change the tilt
+	if(angles[1]<ERS7Info::outputRanges[ERS7Info::HeadOffset+PanOffset][ERS7Info::MinRange] || 
+		 angles[1]>ERS7Info::outputRanges[ERS7Info::HeadOffset+PanOffset][ERS7Info::MaxRange]
+		 ) {
+		double elv=-atan2(target.x,target.z);
+		elv=bound(elv,ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MinRange],ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MaxRange]);
+		angles[0]=elv;
+		if(!getNodAndPan(angles,target))
+			return;
+	}
+
+	// Now we're going to see if the attempted nod is out of range and use the tilt joint if it is.
+	
+	// To find the tilt needed to get into view, we want to find the intersection of:
+	// Hyperbola of intersection of viewing cone with an xz plane through target (y=target's y coordinate)
+	//   ((y-h)/B)^2 - (x/A)^2 = 1
+	//     h: y-intercept of cone
+	//     A: distance from xz plane of target (target's y coordinate aka dy)
+	//     B: drop of top of hyperbola from top of cone (dy*slope)
+	// and the circle formed by points the target could be by rotating around y-axis:
+	//   x^2 + y^2 == r^2
+	//     r: distance from target to y-axis
+	// This gives the following equation: (-Sqrt[x^2*B^2/A^2 + B^2] + h)^2 == r^2 - x^2
+	// ...plug into Mathematica, solve for x, you get this mess: (% means plus/minus aka +/-)
+	//   x = % sqrt( (A^4*(B^2+h^2-r^2) + A^2*B^2*(-B^2+h^2+r^2) % 2*sqrt(A^4*B^2*h^2*(A^4*+B^2*r^2+A^2*(B^2-h^2+r^2)))) / (A^2+B^2)^2 )
+	// (4 solutions)
+	// Or more simply, solve for y instead of x: ((y - h)^2/B^2 - 1)*A^2 == r^2 - y^2
+	//   y = ( A^2*h % sqrt(B^2*(A^4+B^2*r^2+A^2*(B^2-h^2+r^2))) ) / (A^2+B^2)
+	// (2 solutions)
+
+	if(angles[2]<ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MinRange] || 
+		 angles[2]>ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MaxRange]
+		 ) {
+		double nod;
+		if(angles[2]<ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MinRange])
+			nod=ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MinRange];
+		else
+			nod=ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MaxRange];
+		double rad=hypot(target.x,target.z); // aka 'r'
+		double slope=tan(nod);
+		double intcpt=neck_to_nod.z+nod_to_camera.z/cos(nod); // aka 'h'
+		double A=target.y-neck_to_nod.y;
+		double B=A*slope;
+		double yval;
+		if(angles[2]<ERS7Info::outputRanges[ERS7Info::HeadOffset+NodOffset][ERS7Info::MinRange])
+			// too low: use the '-' solution so we get the lower intercept:
+			yval = ( A*A*intcpt - sqrt(B*B*(A*A*A*A+B*B*rad*rad+A*A*(B*B-intcpt*intcpt+rad*rad))) ) / (A*A+B*B);
+		else
+			// too high: use the '+' solution so we get the upper intercept:
+			yval = ( A*A*intcpt + sqrt(B*B*(A*A*A*A+B*B*rad*rad+A*A*(B*B-intcpt*intcpt+rad*rad))) ) / (A*A+B*B);
+		angles[0]=atan2(target.z,target.x)-asin(yval/rad);
+		if(angles[0]<ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MinRange])
+			angles[0]=ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MinRange];
+		else if(angles[0]>ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MaxRange])
+			angles[0]=ERS7Info::outputRanges[ERS7Info::HeadOffset+TiltOffset][ERS7Info::MaxRange];
+		getNodAndPan(angles,target);
+		//sout->printf("rad=%g slope=%g intcpt=%g A=%g B=%g yval=%g tilt=%g\n",rad,slope,intcpt,A,B,yval,angles[0]);
+	}
+
+	/* this is the bad way:
+	//ick:
+	//solve: sqrt(dy^2+(rad*cos(rot)))==slope*(rad*sin(rot)+intcpt)  for rot
+	//mathematica gives:
+	// %acos(%sqrt((-dy2*rad2+slope2*rad2*(intcpt2-dy2+rad2)+slope4*(-intcpt2*rad2+rad4)
+	//             % (2*sqrt(slope4*intcpt2*rad4*(dy2+rad2+slope2*(-intcpt2+dy2+rad2)))))/((1+slope2)*(1+slope2)*rad4)))
+	// where '%' denotes plus/minus aka +/-
+	double rad2=rad*rad;
+	double rad4=rad2*rad2;
+	double slope2=slope*slope;
+	double slope4=slope2*slope2;
+	double dy2=dy*dy;
+	double intcpt2=intcpt*intcpt;
+	double p1=-dy2*rad2+slope2*rad2*(intcpt2-dy2+rad2)+slope4*(-intcpt2*rad2+rad4);
+	double p2=(2*sqrt(slope4*intcpt2*rad4*(dy2+rad2+slope2*(-intcpt2+dy2+rad2))));
+	double p3=(1+slope2)*(1+slope2)*rad4;
+	double telv=atan2(target.z,target.x);
+	if(p1+p2>0)
+	tilt=telv+acos(-sqrt((p1+p2)/p3));
+	sout->printf("telv=%g rad=%g slope=%g intcpt=%g p1=%g p2=%g p3=%g tilt=%g\n",telv,rad,slope,intcpt,p1,p2,p3,tilt);
+	*/
+
+#else //TGT_ERS210,TGT_ERS220,TGT_ERS2xx
+
+	//***********************************************
+	//*************** ERS-210, ERS-220 **************
+	//***********************************************
+
+  double tilt,pan;
+
+  vector3d neck;
+  double height;
+
+#ifdef PLATFORM_APERIOS
+  //pprintf(TextOutputStream,"target (%g,%g,%g) body_angle %g body_height %g\n",
+  //        target.x,target.y,target.z,
+  //        body_angle,body_height);
+#endif
+
+  // translate target so it is relative to base of neck
+  neck = body_to_neck.rotate_y(body_angle);
+  height = body_height + neck.z;
+  target.z -= height;
+  
+  double target_xz_dist; // distance in robot's xz plane of target
+
+  target_xz_dist=hypot(target.x,target.z);
+
+  // assumes that camera is aligned with base of neck
+  // can only see if not too close to neck
+  if(target_xz_dist > neck_to_camera.z && target.length() > neck_to_camera.length()) {
+    double angle_base_target; // angle from base of neck to target xz
+    double angle_base_target_camera; // angle between base and camera from target xz
+    
+    angle_base_target = atan2(target.z,target.x);
+    angle_base_target_camera = asin(neck_to_camera.z/target_xz_dist);
+    
+    tilt = angle_base_target - angle_base_target_camera + body_angle;
+    tilt = bound(tilt,head_tilt_min,head_tilt_max);
+    
+    double camera_dist_to_target;
+    camera_dist_to_target = sqrt(target_xz_dist*target_xz_dist - 
+                                 neck_to_camera.z*neck_to_camera.z);
+    
+    pan = atan2(target.y,camera_dist_to_target);
+    pan = bound(pan,head_pan_min,head_pan_max);
+
+#ifdef PLATFORM_APERIOS
+    //pprintf(TextOutputStream,"txzd %g abt %g abtc %g tilt %g pan %g\n",
+    //        target_xz_dist,angle_base_target,angle_base_target_camera,
+    //        tilt,pan);
+#endif
+  }
+  else {
+    tilt = pan = 0.0;
+  }
+
+  angles[0] = tilt;
+  angles[1] = pan;
+  angles[2] = 0.0; // roll
+	
+#endif //TGT_ERS210,TGT_ERS220,TGT_ERS2xx
+}
+
+vector3d
+RunForwardModel(double *angles, double body_angle, double body_height, vector3d point) {
+  double tilt=0.0,pan=0.0,roll=0.0;
+
+  tilt = angles[0];
+  pan  = angles[1];
+  roll = angles[2];
+
+  point = point.rotate_x(roll);
+  point += neck_to_camera;
+  point = point.rotate_z(pan);
+  point = point.rotate_y(-tilt+body_angle);
+
+  vector3d neck;
+
+  neck = body_to_neck;
+  neck = neck.rotate_y(body_angle);
+  neck.z += body_height;
+
+  point.z += neck.z;
+
+  return point;
+}
+
+// calculates the pose of the camera
+// location  = location of camera in robot coordinates relative to point on ground under neck
+// direction = unit vector pointing in direction of camera
+// up        = unit vector pointing in direction of higher on image
+// right     = unit vector pointing in direction of more right on image
+void GetHeadPosition(vector3d &location, vector3d &direction, vector3d &up, vector3d &right,
+                     double *angles, double body_angle, double body_height)
+{
+  location = RunForwardModel(angles, body_angle, body_height, vector3d(0.0,0.0,0.0));
+
+  vector3d image_x,image_y,image_z;
+
+  image_x = RunForwardModel(angles, body_angle, body_height, vector3d(0.0,-1.0, 0.0));
+  image_y = RunForwardModel(angles, body_angle, body_height, vector3d(0.0, 0.0, 1.0));
+  image_z = RunForwardModel(angles, body_angle, body_height, vector3d(1.0, 0.0, 0.0));
+
+  direction = image_z - location;
+  direction = direction.norm();
+
+  up = image_y - location;
+  up = up.norm();
+
+  right = image_x - location;
+  right = right.norm();
+}
+
+/*! @file
+ * @brief Functions to provide kinematics calculations
+ * @author CMU RoboSoccer 2001-2002 (Creator)
+ * 
+ * @verbinclude CMPack_license.txt
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/05 20:29:04 $
+ */
+
Index: Motion/OldKinematics.h
===================================================================
RCS file: Motion/OldKinematics.h
diff -N Motion/OldKinematics.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/OldKinematics.h	5 Aug 2004 20:29:04 -0000	1.1
@@ -0,0 +1,128 @@
+//-*-c++-*-
+//This class is ported from Carnegie Mellon's 2001 Robosoccer entry, and falls under their license:
+/*=========================================================================
+    CMPack'02 Source Code Release for OPEN-R SDK v1.0
+    Copyright (C) 2002 Multirobot Lab [Project Head: Manuela Veloso]
+    School of Computer Science, Carnegie Mellon University
+  -------------------------------------------------------------------------
+    This software is distributed under the GNU General Public License,
+    version 2.  If you do not have a copy of this licence, visit
+    www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
+    Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
+    in the hope that it will be useful, but WITHOUT ANY WARRANTY,
+    including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  -------------------------------------------------------------------------
+    Additionally licensed to Sony Corporation under the following terms:
+
+    This software is provided by the copyright holders AS IS and any
+    express or implied warranties, including, but not limited to, the
+    implied warranties of merchantability and fitness for a particular
+    purpose are disclaimed.  In no event shall authors be liable for
+    any direct, indirect, incidental, special, exemplary, or consequential
+    damages (including, but not limited to, procurement of substitute
+    goods or services; loss of use, data, or profits; or business
+    interruption) however caused and on any theory of liability, whether
+    in contract, strict liability, or tort (including negligence or
+    otherwise) arising in any way out of the use of this software, even if
+    advised of the possibility of such damage.
+  =========================================================================
+*/
+
+#ifndef __CMPACK_KINEMATICS_H__
+#define __CMPACK_KINEMATICS_H__
+
+#include "Geometry.h"
+#include "Shared/Util.h"
+
+#define RAD(deg) (((deg) * M_PI ) / 180.0)
+#define DEG(rad) (((rad) * 180.0) / M_PI )
+
+extern const double rotator_min ;
+extern const double rotator_max ;
+extern const double shoulder_min;
+extern const double shoulder_max;
+extern const double knee_max    ;
+extern const double knee_min    ;
+
+extern const double rotator_kmin ;
+extern const double rotator_kmax ;
+extern const double shoulder_kmin;
+extern const double shoulder_kmax;
+extern const double knee_kmax    ;
+extern const double f_knee_kmin  ;
+extern const double h_knee_kmin  ;
+
+extern const double tail_min;
+extern const double tail_max;
+
+extern const double head_tilt_min;
+extern const double head_tilt_max;
+extern const double head_pan_min ;
+extern const double head_pan_max ;
+extern const double head_roll_min;
+extern const double head_roll_max;
+
+//! holds the current location of the body, as a delta from when walking started
+/*! @todo get rid of this */
+struct BodyPosition{
+	//! constructor
+	BodyPosition() : loc(), angle() {}
+  vector3d loc;   //!< position of the center of the body
+	vector3d angle; //!< angle of the center of the body
+};
+
+#ifdef TGT_ERS7
+const vector3d body_to_neck    ( 67.50,  0.00,  19.50);
+const vector3d neck_to_nod     ( 00.00,  0.00,  80.00);
+const vector3d nod_to_camera   ( 81.06,  0.00, -14.60);
+const vector3d neck_to_camera  ( 81.06,  0.00,  65.40); //only correct @nod==0
+#else
+const vector3d body_to_neck    ( 75.00,  0.00,  50.00);
+const vector3d neck_to_camera  ( 66.60,  0.00,  48.00);
+//const vector3d neck_to_camera  ( 65.00,  0.00,  48.00);
+#endif
+
+void KinClearErrors();
+int KinGetErrors();
+
+void GetLegAngles(double *angles,vector3d target,int leg);
+void GetLegAngles(double *angles,vector3d target[4],
+                  double body_angle,double body_height);
+void GetLegAngles(double *angles,vector3d target[4],BodyPosition &bp);
+
+void GetLegAngles(double *angles,vector3d target,BodyPosition &bp,int leg);
+void GetLegPosition(vector3d& p,const double* ang,int leg);
+void GetLegPosition(vector3d& p, const double* ang, BodyPosition &bp,int leg);
+
+void GetBodyLocation(vector3d &ball,vector3d &toe,const double *ang,int leg);
+
+// get the tilt,pan,roll angles to point the head towards the target assuming 
+//   the given body_angle/body_height
+void GetHeadAngles(double *angles,vector3d target,
+                   double body_angle,double body_height);
+// converts the camera relative position "point" to a robot centric (under base of neck) position
+//  using the given head angles (tilt/pan/roll) and body_angle and body_height
+vector3d RunForwardModel(double *angles, 
+                         double body_angle, double body_height, 
+                         vector3d point);
+// gets the location of the camera and basis vectors corresponding to the directions of the camera's
+//  z,-y,x corrdinate axis
+void GetHeadPosition(vector3d &location, vector3d &direction, vector3d &up, vector3d &right,
+                     double *angles, double body_angle, double body_height);
+
+
+/*! @file
+ * @brief Functions to provide kinematics calculations
+ * @author CMU RoboSoccer 2001-2002 (Creator)
+ * 
+ * @verbinclude CMPack_license.txt
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/05 20:29:04 $
+ */
+
+#endif
+// __KINEMATICS_H__
Index: Motion/PostureEngine.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/PostureEngine.cc,v
retrieving revision 1.9
retrieving revision 1.21
diff -u -d -r1.9 -r1.21
--- Motion/PostureEngine.cc	7 Sep 2003 22:14:01 -0000	1.9
+++ Motion/PostureEngine.cc	18 Oct 2004 19:53:33 -0000	1.21
@@ -1,5 +1,7 @@
 #include "PostureEngine.h"
 #include "Shared/WorldState.h"
+#include "Motion/roboop/robot.h"
+#include "Shared/Config.h"
 #include <stdio.h>
 
 PostureEngine::~PostureEngine() {}
@@ -9,6 +11,11 @@
 		cmds[i].set(state->outputs[i],1);
 }
 
+void PostureEngine::takeSnapshot(const WorldState* st) {
+	for(unsigned int i=0; i<NumOutputs; i++)
+		cmds[i].set(st->outputs[i],1);
+}
+
 void PostureEngine::clear() {
 	for(unsigned int i=0; i<NumOutputs; i++)
 		cmds[i].unset();
@@ -109,7 +116,6 @@
 	for(unsigned int i=0; i<NumOutputs; i++)
 		if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
 			float dif=cmds[i].value-pe.cmds[i].value;
-			dif*=dif;
 			if(dif>max)
 				max=dif;
 		}
@@ -128,31 +134,60 @@
 unsigned int PostureEngine::LoadBuffer(const char buf[], unsigned int len) {
 	unsigned int origlen=len;
 	clear();
-	if(strncmp("#POS\n",buf,5)!=0) {
-		//		std::cout << "ERROR PostureEngine load corrupted - expected #POS header" << std::endl;
+	if(strncmp("#POS",buf,4)!=0) {
+		// we don't want to display an error here because we may be only testing file type,
+		// so it's up to the caller to decide if it's necessarily an error if the file isn't
+		// a posture
+		//std::cout << "ERROR PostureEngine load corrupted - expected #POS header" << std::endl;
 		return 0;
 	}
 	char formatstring[64];
-	snprintf(formatstring,64,"%%%dc %%f %%f\n%%n",outputNameLen); //std::cout << "Format: " << formatstring << std::endl;
+	snprintf(formatstring,64,"%%%dc %%f %%f%%n",outputNameLen); //std::cout << "Format: " << formatstring << std::endl;
 	unsigned int idx=0;
-	unsigned int linenum=2;
+	unsigned int linenum=1;
 	char jname[outputNameLen+1];
 	jname[outputNameLen]='\0';
 	while(len<=origlen && len>0) {
-		float fval, fwht;
+		float fval, fwht=1;
 		int written;
 		//		printf("%d %.9s\n",linenum+1,buf);
-		if(buf[0]=='#' || buf[0]=='\n') {
-			if(strncmp("#END\n",buf,5)==0)
-				return origlen-len;
-			else {
-				while(*buf++!='\n') {}
+		if(buf[0]=='\r') {
+			buf++; len--;
+			if(buf[0]=='\n') {
+				buf++; len--;
+			}
+			linenum++;
+			continue;
+		}
+		if(buf[0]=='\n') {
+			buf++; len--;
+			linenum++;
+			continue;
+		}
+		if(buf[0]=='#') {
+			if(strncmp("#END\n",buf,5)==0 || strncmp("#END\r",buf,5)==0) {
+				return origlen-len+5;
+			} else if(strncmp("#END\r\n",buf,6)==0) {
+				return origlen-len+6;
+			} else {
+				while(len>0 && *buf!='\n' && *buf!='\r') {len--;buf++;}
+				if(*buf=='\n') { //in case of \r\n
+					buf++;
+					len--;
+				}
+				linenum++;
 				continue;
 			}
 		}
 		written=-1;
 		sscanf(buf,formatstring,jname,&fval,&fwht,&written);
 		if(!ChkAdvance(written,&buf,&len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
+		while(*buf!='\n' && *buf!='\r')
+			buf++;
+		if(buf[0]=='\r' && buf[1]=='\n')
+			buf+=2;
+		else
+			buf++;
 		linenum++;
 		//std::cout << '"' << jname << "\"\t" << (float)fval << '\t' << (float)fwht << std::endl;
 		unsigned int startidx=idx+1;
@@ -168,7 +203,7 @@
 					break;
 			}
 			if(idx==startidx && strcmp(jname,outputNames[idx])!=0)
-				std::cout << "*** WARNING " << jname << " is not a valid joint on this model." << endl;
+				std::cout << "*** WARNING " << jname << " is not a valid joint on this model." << std::endl;
 		}
 	}
 	std::cout << "*** WARNING PostureEngine load missing #END" << std::endl;
@@ -202,25 +237,91 @@
 	return origlen-len;
 }
 
-bool PostureEngine::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg) {
-	if(res>0) {
-		*buf+=res;
-		*len-=res;
-		return true;
-	} else {
-		printf("%s",msg);
-		return false;
+unsigned int PostureEngine::LoadFile(const char filename[]) {
+	return LoadSave::LoadFile(config->motion.makePath(filename).c_str());
+}
+unsigned int PostureEngine::SaveFile(const char filename[]) const {
+	return LoadSave::SaveFile(config->motion.makePath(filename).c_str());
+}
+
+/*
+NEWMAT::ReturnMatrix
+Kinematics::getOrientation(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
 	}
+	update(c,l);
+	NEWMAT::Matrix R;
+	NEWMAT::ColumnVector p;
+	chains[c]->kine(R,p,j);
+	R.Release(); return R;
 }
 
-bool PostureEngine::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1) {
-	if(res>0) {
-		*buf+=res;
-		*len-=res;
-		return true;
-	} else {
-		printf(msg,arg1);
+NEWMAT::ReturnMatrix
+Kinematics::getPosition(unsigned int j) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l)) {
+		NEWMAT::Matrix A(4,4);
+		A<<ROBOOP::fourbyfourident;
+		A.Release(); return A;
+	}
+	update(c,l);
+	NEWMAT::Matrix R;
+	NEWMAT::ColumnVector p;
+	chains[c]->kine(R,p,j);
+	p.Release(); return p;
+}
+*/
+
+bool
+PostureEngine::solveLinkPosition(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink) {
+	unsigned int c=-1U,l=-1U;
+	if(!lookup(j,c,l))
 		return false;
+	update(c,l);
+	bool conv=false;
+	NEWMAT::ColumnVector q=chains[c]->inv_kin_pos(Pobj,0,l,Plink,conv);
+	for(unsigned int i=1; i<=l && i<=chainMaps[c].size(); i++)
+		if(chainMaps[c][i]<NumOutputs)
+			setOutputCmd(chainMaps[c][i],chains[c]->get_q(i));
+	return conv;
+}
+
+bool
+PostureEngine::solveLinkVector(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink) {
+	solveLinkPosition(Pobj,j,Plink);
+	//This method is an approximation, not entirely precise or fast as it could be
+	//Something to work on some more down the road! :)
+	NEWMAT::ColumnVector poE=baseToLink(j)*Pobj;
+	if(poE.nrows()>3 && poE(4)!=0) {
+		poE/=poE(4);
+	}
+	poE=poE.SubMatrix(1,3,1,1);
+	NEWMAT::ColumnVector plE=Plink.SubMatrix(1,3,1,1);
+	if(Plink.nrows()>3 && Plink(4)!=0)
+		plE/=Plink(4);
+	float plE2=plE.SumSquare();
+	float plE_len=sqrt(plE2);
+	float obj_comp_link=NEWMAT::DotProduct(plE,poE)/plE_len;
+	if(obj_comp_link<plE_len)
+		obj_comp_link=obj_comp_link*.975; //.975 is a bit of fudge - accounts for joints moving Plink when adjusting
+	else
+		obj_comp_link=obj_comp_link/.975; //.975 is a bit of fudge - accounts for joints moving Plink when adjusting
+	NEWMAT::ColumnVector obj_proj_link(4);
+	obj_proj_link.SubMatrix(1,3,1,1)=obj_comp_link*plE/plE_len;
+	obj_proj_link(4)=1;
+	return solveLinkPosition(Pobj,j,obj_proj_link);
+}
+
+void
+PostureEngine::update(unsigned int c, unsigned int l) {
+	for(unsigned int j=1; j<=l; j++) {
+		unsigned int tkout=chainMaps[c][j];
+		if(tkout<NumOutputs)
+			chains[c]->set_q(getOutputCmd(tkout).value,j);
 	}
 }
 
@@ -230,8 +331,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
- * $State: Rel $
- * $Date: 2003/09/07 22:14:01 $
+ * $Revision: 1.21 $
+ * $State: Exp $
+ * $Date: 2004/10/18 19:53:33 $
  */
 
Index: Motion/PostureEngine.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/PostureEngine.h,v
retrieving revision 1.3
retrieving revision 1.13
diff -u -d -r1.3 -r1.13
--- Motion/PostureEngine.h	25 Sep 2003 15:27:23 -0000	1.3
+++ Motion/PostureEngine.h	18 Oct 2004 19:53:33 -0000	1.13
@@ -2,26 +2,34 @@
 #ifndef INCLUDED_PostureEngine_h
 #define INCLUDED_PostureEngine_h
 
-#include "OutputCmd.h"
+#include "Motion/OutputCmd.h"
+#include "Motion/Kinematics.h"
 #include "Shared/RobotInfo.h"
 #include "Shared/LoadSave.h"
 
+class WorldState;
+
 //! A class for storing a set of positions and weights for all the outputs
 /*! Handy for any class which wants to deal with setting joints and postures without writing a custom class
  *  @see PostureMC */
-class PostureEngine : public LoadSave {
+class PostureEngine : public LoadSave, public Kinematics {
 public:
 	//!constructor
-	PostureEngine() : LoadSave() {}
-	//!constructor, loads a position from a file - not necessarily quick!
+	PostureEngine() : LoadSave(), Kinematics(*kine) {}
+	//!constructor, loads a position from a file
 	/*! @todo might want to make a library of common positions so they don't have to be loaded repeatedly from memstick */
-	PostureEngine(const char * filename) : LoadSave() { LoadFile(filename); }
+	PostureEngine(const char * filename) : LoadSave(), Kinematics(*kine) { LoadFile(filename); }
+	//!constructor, initializes joint positions to the current state of the outputs as defined by @a state
+	PostureEngine(const WorldState* st) : LoadSave(), Kinematics(*kine) { takeSnapshot(st); }
 	//! destructor
 	virtual ~PostureEngine();
 
 	//! sets the internal #cmds to the current state of the outputs
 	virtual void takeSnapshot();
 
+	//! sets the internal #cmds to the current state of the outputs as defined by @a state
+	virtual void takeSnapshot(const WorldState* st);
+
 	//! sets all joints to unused
 	virtual void clear();
 
@@ -46,20 +54,22 @@
 	virtual PostureEngine createCombine(const PostureEngine& pe) const;
 
 	//! returns the sum squared error between this and pe's output values, but only between outputs which are both not unused
-	/*! @todo create a version which looks at weights?  This doesn't use them. */
+	/*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
 	float diff(const PostureEngine& pe) const;
 	
 	//! returns the average sum squared error between this and pe's output values for outputs which are both not unused
-	/*! @todo create a version which looks at weights?  This doesn't use them. */
+	/*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
 	float avgdiff(const PostureEngine& pe) const;
 	
-	//! returns the max sum squared error between this and pe's output values for outputs which are both not unused
-	/*! @todo create a version which looks at weights?  This doesn't use them. */
+	//! returns the max error between this and pe's output values for outputs which are both not unused
+	/*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
 	float maxdiff(const PostureEngine& pe) const;
 	
 	//! NOT VIRTUAL! You should be able to call this to set outputs without checking out, just a peekMotion().  Theoretically.
 	//!@name Output Accessors
 	inline PostureEngine& setOutputCmd(unsigned int i, const OutputCmd& c) { cmds[i]=c; return *this; } //!<sets output @a i to OutputCmd @a c, returns @c *this so you can chain them
+	inline OutputCmd& operator()(unsigned int i) { return cmds[i]; } //!< returns output @a i, returns a reference so you can also set "through" this call.
+	inline const OutputCmd& operator()(unsigned int i) const { return cmds[i]; } //!< returns output @a i
 	inline OutputCmd& getOutputCmd(unsigned int i) { return cmds[i]; } //!< returns output @a i, returns a reference so you can also set "through" this call.
 	inline const OutputCmd& getOutputCmd(unsigned int i) const { return cmds[i]; } //!< returns output @a i
 	//@}
@@ -69,14 +79,26 @@
 	virtual unsigned int getBinSize() const;
 	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
 	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
+	virtual unsigned int LoadFile(const char filename[]);
+	virtual unsigned int SaveFile(const char filename[]) const;
 	//@}
 
+	//! Performs inverse kinematics to solve for positioning @a Plink on link @a j to @a Pobj in base coordinates (expects homogenous form); if solution found, stores result in this posture and returns true
+	bool solveLinkPosition(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink);
+	//! Performs inverse kinematics to solve for positioning Plink on link @a j to Pobj in base coordinates; if solution found, stores result in this posture and returns true
+	bool solveLinkPosition(float Pobj_x, float Pobj_y, float Pobj_z, unsigned int j, float Plink_x, float Plink_y, float Plink_z)
+	{ return solveLinkPosition(pack(Pobj_x,Pobj_y,Pobj_z),j,pack(Plink_x,Plink_y,Plink_z)); }
+
+	//! Performs inverse kinematics to solve for positioning @a Plink on link @a j to @a Pobj in base coordinates (expects homogenous form); if solution found, stores result in this posture and returns true
+	bool solveLinkVector(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink);
+	//! Performs inverse kinematics to solve for positioning Plink on link @a j to Pobj in base coordinates; if solution found, stores result in this posture and returns true
+	bool solveLinkVector(float Pobj_x, float Pobj_y, float Pobj_z, unsigned int j, float Plink_x, float Plink_y, float Plink_z)
+	{ return solveLinkVector(pack(Pobj_x,Pobj_y,Pobj_z),j,pack(Plink_x,Plink_y,Plink_z)); }
+
 protected:
-	//!used by LoadBuffer()/SaveBuffer(), checks to see if the amount read/written (@a res) is nonzero, increments @a buf, decrements @a len, or displays @a msg if @a is zero
-	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg);
-	//!used by LoadBuffer()/SaveBuffer(), checks to see if the amount read/written (@a res) is nonzero, increments @a buf, decrements @a len, or displays @a msg with @a arg1 if @a is zero
-	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1);
-	
+	//all updates come from this posture engine's own state, not WorldState
+	virtual void update(unsigned int c, unsigned int l);
+
 	//!the table of outputs' values and weights, can be accessed through setOutputCmd() and getOutputCmd()
 	OutputCmd cmds[NumOutputs];
 };
@@ -88,9 +110,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
- * $State: Rel $
- * $Date: 2003/09/25 15:27:23 $
+ * $Revision: 1.13 $
+ * $State: Exp $
+ * $Date: 2004/10/18 19:53:33 $
  */
 
 #endif
Index: Motion/PostureMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/PostureMC.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Motion/PostureMC.h	3 Mar 2004 03:37:13 -0000	1.7
+++ Motion/PostureMC.h	30 Aug 2004 20:26:45 -0000	1.8
@@ -6,6 +6,8 @@
 #include "PostureEngine.h"
 #include "MotionManager.h"
 
+class WorldState;
+
 //! a MotionCommand shell for PostureEngine
 /*! Will autoprune by default once it reaches the target pose.
  * 
@@ -19,6 +21,8 @@
 	PostureMC() : MotionCommand(),PostureEngine(),dirty(true),tolerance(.01) { }
 	//!constructor, loads from @a filename
 	PostureMC(const char* filename) : MotionCommand(),PostureEngine(filename),dirty(true),tolerance(.01) { }
+	//!constructor, initializes joint positions to the current state of the outputs as defined by @a state
+	PostureMC(const WorldState* st) : MotionCommand(),PostureEngine(st),dirty(true),tolerance(.01) { }
 	//!destructor
 	virtual ~PostureMC() {}
 	
@@ -61,6 +65,7 @@
 	//!Had to override stuff to manage a dirty flag
 	//!@name PostureEngine Stuff
 	inline virtual void takeSnapshot() { dirty=true; PostureEngine::takeSnapshot(); }
+	inline virtual void takeSnapshot(const WorldState* st) { dirty=true; PostureEngine::takeSnapshot(st); }
 	inline virtual void clear() { dirty=true; PostureEngine::clear(); }
 	inline virtual PostureEngine& setOverlay(const PostureEngine& pe) { dirty=true; PostureEngine::setOverlay(pe); return *this; }
 	inline virtual PostureEngine& setUnderlay(const PostureEngine& pe) { dirty=true; PostureEngine::setUnderlay(pe); return *this; }
@@ -88,9 +93,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2004/03/03 03:37:13 $
+ * $Date: 2004/08/30 20:26:45 $
  */
 
 #endif
Index: Motion/WalkMC.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/WalkMC.cc,v
retrieving revision 1.23
retrieving revision 1.29
diff -u -d -r1.23 -r1.29
--- Motion/WalkMC.cc	26 Feb 2004 01:02:49 -0000	1.23
+++ Motion/WalkMC.cc	24 Jul 2004 03:10:59 -0000	1.29
@@ -33,6 +33,7 @@
 #include "Events/EventRouter.h"
 #include "Events/LocomotionEvent.h"
 #include "Wireless/Socket.h"
+#include "Shared/Config.h"
 
 #include "Motion/MotionManager.h"
 
@@ -58,16 +59,17 @@
 unsigned int checksum(const char *data,int num); //!< computes a file checksum
 
 WalkMC::WalkMC(const char* pfile/*=NULL*/)
-// tss "SmoothWalk" modification follows
-//	: MotionCommand(), isPaused(false), wp(), body_loc(), body_angle(),
-//		pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
-//		time(get_time()), TimeStep(FrameTime), vel_xya(0,0,0),
-//		target_vel_xya(0,0,0)
+	// tss "SmoothWalk" modification follows
+	//	: MotionCommand(), isPaused(false), wp(), body_loc(), body_angle(),
+	//		pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
+	//		time(get_time()), TimeStep(FrameTime), vel_xya(0,0,0),
+	//		target_vel_xya(0,0,0)
+
 	: MotionCommand(), isPaused(false), wp(), cp(), body_loc(), body_angle(),
-		pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
-		time(get_time()), TimeStep(FrameTime), slowmo(1.0f),
-		CycleOffset(0), TimeOffset(0), NewCycleOffset(false),
-			vel_xya(0,0,0), target_vel_xya(0,0,0), last_target_vel_xya(0,0,0)
+				pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
+				time(get_time()), TimeStep(FrameTime), slowmo(1.0f),
+				CycleOffset(0), TimeOffset(0), NewCycleOffset(false),
+				vel_xya(0,0,0), target_vel_xya(0,0,0), last_target_vel_xya(0,0,0)
 {
 	init(pfile);
 }
@@ -115,7 +117,7 @@
 	if(pfile!=NULL)
 		LoadFile(pfile);
 	else
-		LoadFile("/ms/data/motion/walk.prm");
+		LoadFile(config->motion.walk.c_str());
 
 	double zeros[JointsPerLeg];
 	for(unsigned int i=0; i<JointsPerLeg; i++)
@@ -141,7 +143,7 @@
 	
 unsigned int WalkMC::getBinSize() const {
 	unsigned int used=0;
-	used+=creatorSize("WalkMC");
+	used+=creatorSize("WalkMC-2.2");
 	used+=sizeof(wp);
 	used+=sizeof(cp);
 	return used;	
@@ -150,38 +152,83 @@
 unsigned int WalkMC::LoadBuffer(const char buf[], unsigned int len) {
 	unsigned int origlen=len;
 	unsigned int used=0;
-	if(0==(used=checkCreator("WalkMC",buf,len,false))) {
-		// backwards compatability - if there's no creator code, just assume it's a straight WalkParam
-		sout->printf("Assuming old-format walk parameter file\n");
+	if((used=checkCreator("WalkMC-2.2",buf,len,false))!=0) {
+		len-=used; buf+=used;
 		if(len>=sizeof(WalkParam))
 			memcpy(&wp,buf,used=sizeof(WalkParam));
 		else
 			return 0;
 		len-=used; buf+=used;
+		if(len>=sizeof(CalibrationParam))
+			memcpy(&cp,buf,used=sizeof(CalibrationParam));
+		else
+			memcpy(&cp,buf,used=len);
+		//return 0;
+		len-=used; buf+=used;
+		//sout->printf("Loaded WalkMC Parameters n=%ud checksum=0x%X\n",origlen-len,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)+sizeof(cp)));
+		return origlen-len;	
+	} else if((used=checkCreator("WalkMC",buf,len,false))!=0) {
+		sout->printf("Pre-version 2.2 walk parameter file\n");
+		len-=used; buf+=used;
+		for(unsigned int i=0; i<4; i++) {
+			if(len>=sizeof(LegParam))
+				memcpy(&wp.leg[i],buf,used=sizeof(LegParam));
+			else
+				return 0;
+			len-=used; buf+=used;
+		}
+		if(0==(used=decode(wp.body_height,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.body_angle,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.hop,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.sway,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.period,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.useDiffDrive,buf,len))) return 0;
+		len-=used; buf+=used;
+		wp.sag=0;
+		if(len>=sizeof(CalibrationParam))
+			memcpy(&cp,buf,used=sizeof(CalibrationParam));
+		else
+			return 0;
+		len-=used; buf+=used;
+		//sout->printf("Loaded WalkMC Parameters n=%ud checksum=0x%X\n",origlen-len,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)+sizeof(cp)));
+		return origlen-len;	
+	} else {
+		// backwards compatability - if there's no creator code, just assume it's a straight WalkParam
+		sout->printf("Assuming old-format walk parameter file\n");
+		for(unsigned int i=0; i<4; i++) {
+			if(len>=sizeof(LegParam))
+				memcpy(&wp.leg[i],buf,used=sizeof(LegParam));
+			else
+				return 0;
+			len-=used; buf+=used;
+		}
+		if(0==(used=decode(wp.body_height,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.body_angle,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.hop,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.sway,buf,len))) return 0;
+		len-=used; buf+=used;
+		if(0==(used=decode(wp.period,buf,len))) return 0;
+		len-=used; buf+=used;
+		wp.useDiffDrive=0;
+		wp.sag=0;
 		cp=CalibrationParam();
 		//sout->printf("Loaded WalkMC Parameters n=%ud checksum=0x%X\n",origlen-len,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)));
 		return origlen-len;	
 	}
-	len-=used; buf+=used;
-	if(len>=sizeof(WalkParam))
-		memcpy(&wp,buf,used=sizeof(WalkParam));
-	else
-		return 0;
-	len-=used; buf+=used;
-	if(len>=sizeof(CalibrationParam))
-		memcpy(&cp,buf,used=sizeof(CalibrationParam));
-	else
-		memcpy(&cp,buf,used=len);
-	//return 0;
-	len-=used; buf+=used;
-	//sout->printf("Loaded WalkMC Parameters n=%ud checksum=0x%X\n",origlen-len,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)+sizeof(cp)));
-	return origlen-len;	
 }
 
 unsigned int WalkMC::SaveBuffer(char buf[], unsigned int len) const {
 	unsigned int origlen=len;
 	unsigned int used=0;
-	if(0==(used=saveCreator("WalkMC",buf,len))) return 0;
+	if(0==(used=saveCreator("WalkMC-2.2",buf,len))) return 0;
 	len-=used; buf+=used;
 	if(len>=sizeof(WalkParam))
 		memcpy(buf,&wp,used=sizeof(WalkParam));
@@ -197,6 +244,13 @@
 	return origlen-len;
 }
 
+unsigned int WalkMC::LoadFile(const char* filename) {
+	return LoadSave::LoadFile(config->motion.makePath(filename).c_str());
+}
+unsigned int WalkMC::SaveFile(const char* filename) const {
+	return LoadSave::SaveFile(config->motion.makePath(filename).c_str());
+}
+
 void WalkMC::setTargetVelocity(double dx,double dy,double da)
 {
 #ifdef BOUND_MOTION
@@ -235,7 +289,7 @@
 		travelTime=curT;
 	}
 	
-  double t = TimeStep * slowmo / 1000;
+  float tm = TimeStep * slowmo / 1000;
 
 	vector3d cal_target_vel_xya(target_vel_xya);
 	if(target_vel_xya.x<0)
@@ -251,16 +305,16 @@
 			applyCalibration(cp.f_calibration,target_vel_xya,cal_target_vel_xya);
 
   //software accel:
-	vel_xya.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*t, vel_xya.x+max_accel_xya.x*t);
-  vel_xya.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*t, vel_xya.y+max_accel_xya.y*t);
-  vel_xya.z = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*t, vel_xya.z+max_accel_xya.z*t);
+	vel_xya.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*tm, vel_xya.x+max_accel_xya.x*tm);
+  vel_xya.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*tm, vel_xya.y+max_accel_xya.y*tm);
+  vel_xya.z = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
 	//no software accel:
 	//vel_xya=cal_target_vel_xya;
 	//<end>
 
   BodyPosition delta;
-  delta.loc.set(vel_xya.x*t,vel_xya.y*t,0);
-  delta.angle.set(0,0,vel_xya.z*t);
+  delta.loc.set(vel_xya.x*tm,vel_xya.y*tm,0);
+  delta.angle.set(0,0,vel_xya.z*tm);
 
 	time=(int)(curT*slowmo);
 
@@ -303,8 +357,20 @@
 		//		cout << "loop,,," << flush;
 		for(unsigned int i=0; i<NumLegs; i++){
 
-			bool air = (cycle >= wp.leg[i].lift_time) && (cycle < wp.leg[i].down_time);
-			double air_f = wp.leg[i].down_time - wp.leg[i].lift_time;
+			//interpret a down time before a lift time as a request to move the leg in reverse (has its uses)
+			float lift_time=wp.leg[i].lift_time;
+			float down_time=wp.leg[i].down_time;
+			float dir=1;
+			if(down_time==lift_time)
+				dir=0;
+			else if(down_time<lift_time) {
+				lift_time=wp.leg[i].down_time;
+				down_time=wp.leg[i].lift_time;
+				dir=-1;
+			}
+
+			bool air = (cycle >= lift_time) && (cycle < down_time);
+			double air_f = down_time - lift_time;
 			double nextlegangles[JointsPerLeg];
 
 			if(air != legw[i].air){
@@ -317,12 +383,12 @@
 							cout << nextlegangles[j] << ' ';
 						cout << endl;
 					*/
-					t = wp.period/1000.0 * 0.75;
+					tm = wp.period/1000.0 * 0.75; //wtf is the 0.75 based on?  Don't ask me, i just work here! (ejt)
 					vector3d vfp;
 					//software accel:
-					vfp.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*t, vel_xya.x+max_accel_xya.x*t);
-					vfp.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*t, vel_xya.y+max_accel_xya.y*t);
-					double vfa   = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*t, vel_xya.z+max_accel_xya.z*t);
+					vfp.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*tm, vel_xya.x+max_accel_xya.x*tm);
+					vfp.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*tm, vel_xya.y+max_accel_xya.y*tm);
+					double vfa   = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
 					//no software accel:
 					//vfp.x=cal_target_vel_xya.x;
 					//vfp.y=cal_target_vel_xya.y;
@@ -330,17 +396,29 @@
 					//<end>
 					vfp.z = 0.0;
 					double b = (wp.period/1000.0) * (1.0 - air_f) / 2.0;
-					vector3d target = (wp.leg[i].neutral + vfp*b).rotate_z(vfa*b);
+					vector3d target;
+					if(wp.useDiffDrive) {
+						float rot = vfa/cp.max_vel[CalibrationParam::rotate];
+						if((i&1)==0)
+							rot=-rot;
+						vfp.x += cp.max_vel[CalibrationParam::forward]*rot;
+						target = (wp.leg[i].neutral + vfp*b*dir);
+					} else {
+						target = (wp.leg[i].neutral + vfp*b*dir).rotate_z(vfa*b);
+					}
+					target.z+=wp.sag;
+					liftPos[i]=legpos[i];
+					downPos[i]=target;
 					legw[i].airpath.create(legpos[i],target,wp.leg[i].lift_vel,wp.leg[i].down_vel);
 				}else{
-					legpos[i].z = 0.0;
+					legpos[i].z = wp.leg[i].neutral.z;
 				}
 				legw[i].air = air;
 			}
 
 			if(air){
-				t = (cycle - wp.leg[i].lift_time) / air_f;
-				legpos[i] = legw[i].airpath.eval(t);
+				legw[i].cyc = (cycle - lift_time) / air_f;
+				legpos[i] = legw[i].airpath.eval(legw[i].cyc);
 
 // Core tss "SmoothWalk" addition follows
 				// KLUDGY MOD. Goal: reduce the height of the
@@ -371,7 +449,21 @@
 				legpos[i].z *= 1-velfraction;
 // Core tss "SmoothWalk" addition ends
 			}else{
-				legpos[i] = (legpos[i] - delta.loc).rotate_z(-delta.angle.z);
+				if(dir==0)
+					legpos[i]=wp.leg[i].neutral;
+				else {
+					if(wp.useDiffDrive) {
+						tm = wp.period/1000.0 * 0.75; //wtf is the 0.75 based on?  Don't ask me, i just work here! (ejt)
+						double vfa   = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
+						legpos[i] -= delta.loc*dir;
+						float rot = vfa/cp.max_vel[CalibrationParam::rotate]*TimeStep * slowmo / 1000;
+						if((i&1)==0)
+							rot=-rot;
+						legpos[i].x -= cp.max_vel[CalibrationParam::forward]*rot;
+					} else {
+						legpos[i] = (legpos[i] - delta.loc*dir).rotate_z(-delta.angle.z);
+					}
+				}
 			}
 
 			GetLegAngles(nextlegangles,legpos[i],nextpos,i);
@@ -453,8 +545,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.23 $
+ * $Revision: 1.29 $
  * $State: Exp $
- * $Date: 2004/02/26 01:02:49 $
+ * $Date: 2004/07/24 03:10:59 $
  */
 
Index: Motion/WalkMC.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Motion/WalkMC.h,v
retrieving revision 1.21
retrieving revision 1.27
diff -u -d -r1.21 -r1.27
--- Motion/WalkMC.h	3 Mar 2004 18:42:16 -0000	1.21
+++ Motion/WalkMC.h	5 Aug 2004 20:29:04 -0000	1.27
@@ -34,7 +34,7 @@
 
 #include "MotionCommand.h"
 #include "Geometry.h"
-#include "Kinematics.h"
+#include "OldKinematics.h"
 #include "Path.h"
 #include "Shared/get_time.h"
 #include "OutputCmd.h"
@@ -67,19 +67,18 @@
  *
  *  This portion of the code falls under CMPack's license:
  *  @verbinclude CMPack_license.txt
- *
- *  @bug the legs try (briefly) to straighten out when first starting to move
  */
 class WalkMC : public MotionCommand, public LoadSave {
 public:
-	typedef SplinePath<vector3d,double> splinepath; //!<for convenience
-	typedef HermiteSplineSegment<vector3d,double> spline; //!<for convenience
+	typedef SplinePath<vector3d,float> splinepath; //!<for convenience
+	typedef HermiteSplineSegment<vector3d,float> spline; //!<for convenience
 
 	//! holds state about each leg's path
 	struct LegWalkState {
-		LegWalkState() : airpath(), air(0) {} //!< constructor
+		LegWalkState() : airpath(), air(0), cyc(0) {} //!< constructor
 		spline airpath; //!< the path to follow
 		bool air; //!< true if in the air
+		float cyc; //!< % (0,1) of how far along the path we are
 	};
 	
 	//! holds parameters about how to move each leg
@@ -94,14 +93,16 @@
 
 	//! holds more general parameters about the walk
 	struct WalkParam {
-		WalkParam() : body_height(0), body_angle(0), hop(0), sway(0), period(0), reserved() {} //!< constructor
+		WalkParam() : body_height(0), body_angle(0), hop(0), sway(0), period(0), useDiffDrive(0), sag(0), reserved() {} //!< constructor
 		LegParam leg[4]; //!< a set of LegParam's, one for each leg
 		double body_height; //!< the height to hold the body (mm)
 		double body_angle; //!< the angle to hold the body (rad - 0 is level)
 		double hop;  //!< sinusoidal hop amplitude
 		double sway; //!< sinusoidal sway in y direction
 		long period; //!< the time between steps
-		long reserved; //!< live with it
+		long useDiffDrive; //!< if non-zero, diff-drive style turning is used instead of rotational turning
+		float sag; //!< the amount to sagging to account for when a foot is lifted
+		float reserved; //!< just live with it
 	};
 
 	//! holds information to correct for slippage, non-idealities
@@ -141,6 +142,8 @@
 	virtual unsigned int getBinSize() const;
 	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
 	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
+	virtual	unsigned int LoadFile(const char* filename);
+	virtual unsigned int SaveFile(const char* filename) const;
 
 	//! set the direction to walk - can specify x (forward), y (left), and angular (counterclockwise) velocities
 	void setTargetVelocity(double dx,double dy,double da);
@@ -168,6 +171,8 @@
 	void setSlowMo(float p) { slowmo=p; } //!< sets slowmo
 	float* getSlowMo() { return &slowmo; } //!< gets slowmo
 
+	const vector3d& getLegPosition(LegOrder_t i) const { return legpos[i]; }
+
 	WalkParam & getWP() { return wp; }; //!< returns the current walk parameter structure
 	CalibrationParam & getCP() { return cp; }; //!< returns the current walk calibration parameter
 	
@@ -200,9 +205,11 @@
 	vector3d legpos[NumLegs]; //!< current position of each leg
 	splinepath body_loc; //!< the path the body goes through while walking (?)
 	splinepath body_angle; //!< the path the body goes through while walking (?)
+	vector3d liftPos[NumLegs]; //!< position each of the feet was last lifted
+	vector3d downPos[NumLegs]; //!< position each of the feet is next going to be set down
 
 	vector3d pos_delta; //!< how much we've moved
-	double angle_delta; //!< how much we've turned
+	float angle_delta; //!< how much we've turned
 	
 	unsigned int travelTime; //!< the time of the last call to setTargetVelocity - handy to check the time we've been traveling current vector
 	int time; //!< time of last call to updateJointCmds() (scaled by slowmo)
@@ -263,9 +270,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.21 $
+ * $Revision: 1.27 $
  * $State: Exp $
- * $Date: 2004/03/03 18:42:16 $
+ * $Date: 2004/08/05 20:29:04 $
  */
 
 #endif
Index: Motion/WaypointEngine.h
===================================================================
RCS file: Motion/WaypointEngine.h
diff -N Motion/WaypointEngine.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/WaypointEngine.h	27 Jul 2004 14:33:59 -0000	1.4
@@ -0,0 +1,759 @@
+//-*-c++-*-
+#ifndef INCLUDED_WaypointEngine_h_
+#define INCLUDED_WaypointEngine_h_
+
+#include "Shared/ListMemBuf.h"
+#include "Shared/LoadSave.h"
+
+//! Provides computation and management of a desired path through a series of waypoints
+/*! This is a generalized set of data structures and management code -
+ *  it doesn't actually say anything about @e how you get from one
+ *  waypoint to the other, it will just tell you where you should be
+ *  going at any given time.
+ *
+ *  So, for instance, you may be interested in WaypointWalk, which
+ *  will use a WalkMC to traverse the waypoints.  Future development
+ *  may include a WaypointPush, to push an object along a path instead
+ *  of just moving the body along a path.
+ *
+ *  Although general curves between waypoints are not supported, you
+ *  can use either circular arcs or straight lines.
+ *
+ *  The Waypoint class holds the actual data about each waypoint.  You
+ *  can specify waypoints in 3 ways, egocentric, offset, and absolute.
+ *  - Egocentric: the x and y parameters are relative to the body
+ *    itself; x is always forward and y is always left.  Handy for
+ *    turtle/logo style specification of a series of instructions which
+ *    specify the waypoints.
+ *  - Offset: the x and y parameters are relative to the current body
+ *    position, but not its heading.
+ *  - Absolute: the x and y parameters are direct coordinates
+ *
+ *  In addition, you can specify how to handle the heading of the body
+ *  while the path is executing.  You can specify a relative offset to
+ *  the direction of travel (for instance, to walk sideways instead of
+ *  forward), or an absolute value (to always face a certain direction
+ *  while traveling)
+ *
+ *  Dead reckoning is very prone to accruing error.  It is highly
+ *  recommended that you calibrate the locomotion mechanism carefully
+ *  and implement some form of localization to handle the inevitable
+ *  drift.
+ *
+ *  Waypoint list files are a fairly straightforward plain text format.
+ *  The extension .wyp is suggested.
+ *
+ *  The format is:
+ *  - '<tt>#WyP</tt>' - header to verify file type
+ *  - A series of entries:
+ *    - '<tt>max_turn_speed </tt><i>num</i>' - sets the maximum error-correction turning speed used for all following waypoints
+ *    - '<tt>track_path </tt><i>bool</i>' - sets trackpath mode on or off for all following waypoints (see Waypoint::trackPath)
+ *    - '<tt>add_point </tt>{<tt>ego</tt>|<tt>off</tt>|<tt>abs</tt>}<tt> </tt><i>x_val</i><tt> </tt><i>y_val</i><tt> </tt>{<tt>hold</tt>|<tt>follow</tt>}<tt> </tt><i>angle_val</i><tt> </tt><i>speed_val</i><tt> </tt><i>arc_val</i>' - adds the waypoint with the parameters given, see Waypoint, similar to add*Waypoint functions
+ *    - '<tt>add_arc </tt>{<tt>ego</tt>|<tt>off</tt>|<tt>abs</tt>}<tt> </tt><i>x_val</i><tt> </tt><i>y_val</i><tt> </tt>{<tt>hold</tt>|<tt>follow</tt>}<tt> </tt><i>angle_val</i><tt> </tt><i>speed_val</i><tt> </tt><i>arc_val</i>' - adds the waypoint with the parameters given, see Waypoint, similar to add*Arc functions
+ *  - '<tt>#END</tt>' - footer to verify ending of file
+ */
+template<unsigned int MAX_WAY>
+class WaypointEngine : public LoadSave {
+public:
+	static const unsigned int MAX_WAYPOINTS=MAX_WAY; //!< for external access to maximum waypoints
+
+	//! Holds information about each waypoint, see WaypointEngine for overview
+	struct Waypoint {
+		//! defines different ways to interpret the position values
+		enum posType_t {
+			POSTYPE_EGOCENTRIC, //!< #x and #y are relative to current heading - so x is forward and y is strafe
+			POSTYPE_OFFSET, //!< #x and #y are oriented with the coordinates, but relative to current location (delta x and delta y)
+			POSTYPE_ABSOLUTE //!< #x and #y are a specific coordinate location
+		};
+		Waypoint()
+			: x(0), y(0), angle(0), arc(), speed(), turnSpeed(), posType(), angleIsRelative(), trackPath()
+		{} //!< constructor
+		Waypoint(float xc, float yc, Waypoint::posType_t pos_rel, float ac, bool ang_rel, float spd, bool track, float turn)
+			: x(xc), y(yc), angle(ac), arc(0), speed(spd), turnSpeed(turn), posType(pos_rel), angleIsRelative(ang_rel), trackPath(track)
+		{} //!< constructor
+		float x; //!< the displacement along x (meters), subject to #posType
+		float y; //!< the displacement along y (meters), subject to #posType
+		float angle; //!< either the angle relative to path to maintain, or the heading to maintain, see #angleIsRelative
+		float arc; //!< angle of sector of arc to use to get to waypoint (0 means straight line)
+		float speed; //!< speed (in meters per second)
+		float turnSpeed; //!< maximum speed to correct heading (in radians per second)
+		posType_t posType; //!< lets us know how to interpret the #x and #y values
+		bool angleIsRelative; //!< if true, #angle is interpreted as relative to the path; otherwise, interpreted as an absolute heading to maintain
+		bool trackPath; //!< if true, if off course, will attempt to get back on path at the ideal location; if false, simply heads directly for waypoint from whereever it is
+	};
+
+	typedef ListMemBuf<Waypoint,MAX_WAYPOINTS> WaypointList_t; //!< convenient shorthand
+	typedef typename ListMemBuf<Waypoint,MAX_WAYPOINTS>::index_t WaypointListIter_t; //!< convenient shorthand
+
+	//! constructor
+	WaypointEngine()
+		: LoadSave(), waypoints(), isRunning(false), isLooping(true), isTracking(false),
+			curWaypoint(waypoints.end()), waypointTime(0), waypointDistance(0), pathLength(0), arcRadius(0),
+			lastUpdateTime(0), Pcorr(.5), turnSpeed(.65)
+	{init();}
+	//! constructor
+	WaypointEngine(char * f)
+		: LoadSave(), waypoints(), isRunning(false), isLooping(true), isTracking(false),
+			curWaypoint(waypoints.end()), waypointTime(0), waypointDistance(0), pathLength(0), arcRadius(0),
+			lastUpdateTime(0), Pcorr(.5), turnSpeed(.65)
+	{init(); LoadFile(f); }
+
+	//! returns a rough overestimate of the size needed
+	/*! pretends we need to switch max_turn_speed and track_path on
+		every point, and the longest options are given for every point */
+	virtual unsigned int getBinSize() const;
+	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
+	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
+
+	virtual void go();      //!< starts walking towards the first waypoint
+	virtual void pause();   //!< halts execution of waypoint list
+	virtual void unpause(); //!< resumes execution of waypoint list from last paused location
+
+	virtual void setIsLooping(bool isl) { isLooping=isl; } //!< sets #isLooping
+	virtual bool getIsLooping() const { return isLooping; } //!< returns #isLooping
+
+	virtual WaypointList_t& getWaypointList() { return waypoints; } //!< returns a reference to #waypoints
+	virtual const WaypointList_t& getWaypointList() const { return waypoints; } //!< returns a const reference to #waypoints
+
+	virtual WaypointListIter_t getCurWaypointID() const { return curWaypoint; } //!< returns id value of current waypoint (#curWaypoint)
+
+	virtual float getCurX() const { return curPos[0]; } //!< returns current x position
+	virtual float getCurY() const { return curPos[1]; } //!< returns current y position
+	virtual float getCurA() const { return curPos[2]; } //!< returns current heading
+	//! sets the current position (for instance your localization module has an update)
+	virtual void setCurPos(float x, float y, float a) {
+		curPos[0]=x; curPos[1]=y; curPos[2]=a;
+	}
+
+	//! call this on each opportunity to check current location and correct velocities
+	/*! @return #isRunning for convenience of checking if anything is happening */
+	virtual bool cycle(); 
+
+	//!these are for convenience - can also directly edit the waypoint list using access from getWaypointList()
+	//!@name Adding Waypoints
+
+	//! adds a waypoint to the end of the list, allows you to specify turtle-style instructions
+	/*! @param forward distance forward to move (negative to move backward of course)
+	 *  @param left distance to the left to move (negative to move right of course)
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second */
+	virtual void addEgocentricWaypoint(float forward, float left, float angle, bool angleIsRelative, float speed) {
+		waypoints.push_back(Waypoint(forward,left,Waypoint::POSTYPE_EGOCENTRIC,angle,angleIsRelative,speed,isTracking,turnSpeed));
+	}
+	//! adds a waypoint to the end of the list, allows you to set locations relative to the location of the previous waypoint (or starting position)
+	/*! @param x distance delta along x axis of the waypoint
+	 *  @param y distance delta along y axis of the waypoint
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second */
+	virtual void addOffsetWaypoint(float x, float y, float angle, bool angleIsRelative, float speed) {
+		waypoints.push_back(Waypoint(x,y,Waypoint::POSTYPE_OFFSET,angle,angleIsRelative,speed,isTracking,turnSpeed));
+	}
+	//! adds a waypoint to the end of the list, allows you to set locations relative to the location of the previous waypoint (or starting position)
+	/*! @param x position along x axis of the waypoint
+	 *  @param y position along y axis of the waypoint
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second */
+	virtual void addAbsoluteWaypoint(float x, float y, float angle, bool angleIsRelative, float speed) {
+		waypoints.push_back(Waypoint(x,y,Waypoint::POSTYPE_ABSOLUTE,angle,angleIsRelative,speed,isTracking,turnSpeed));
+	}
+
+	//! adds a waypoint to the end of the list, using an arcing path to get there, allows you to specify turtle-style instructions to specify the focus of the arc
+	/*! If you would rather specify the ending point and then "bow" the path, try addEgocentricWaypoint() followed by setting the Waypoint::arc field directly
+	 *  @param forward distance in front of the center of the circle of the arc
+	 *  @param left distance to the left of the center of the circle of the arc
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second
+	 *  @param arc is the number of radians the arc fills; arcs near 0 (or multiples of 360) may cause numeric instability*/
+	virtual void addEgocentricArc(float forward, float left, float angle, bool angleIsRelative, float speed, float arc) {
+		addEgocentricWaypoint(forward,left,angle,angleIsRelative,speed);
+		fixArc(arc);
+	}
+	//! adds a waypoint to the end of the list, using an arcing path to get there, allows you to specify locations relative to previous waypoint to specify the focus of the arc
+	/*! If you would rather specify the ending point and then "bow" the path, try addOffsetWaypoint() followed by setting the Waypoint::arc field directly
+	 *  @param x distance delta along x of the center of the circle of the arc
+	 *  @param y distance delta along y of the center of the circle of the arc
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second
+	 *  @param arc is the number of radians the arc fills; arcs near 0 (or multiples of 360) may cause numeric instability*/
+	virtual void addOffsetArc(float x, float y, float angle, bool angleIsRelative, float speed, float arc) {
+		addOffsetWaypoint(x,y,angle,angleIsRelative,speed);
+		fixArc(arc);
+	}
+	//! adds a waypoint to the end of the list, using an arcing path to get there, allows you to specify absolute locations to specify the focus of the arc
+	/*! If you would rather specify the ending point and then "bow" the path, try addAbsoluteWaypoint() followed by setting the Waypoint::arc field directly
+	 *  @param x position along x of the center of the circle of the arc
+	 *  @param y position along y of the center of the circle of the arc
+	 *  @param angle angle of attack to use on the path
+	 *  @param angleIsRelative controls interpretation of @a angle; true means angle specifies an offset from the bearing of the target waypoint, false means maintain an absolute heading
+	 *  @param speed is the speed to move at; meters per second
+	 *  @param arc is the number of radians the arc fills; arcs near 0 (or multiples of 360) may cause numeric instability*/
+	virtual void addAbsoluteArc(float x, float y, float angle, bool angleIsRelative, float speed, float arc) {
+		addAbsoluteWaypoint(x,y,angle,angleIsRelative,speed);
+		fixArc(arc);
+	}
+
+	//@}
+	
+	//! will set the currently active waypoint to another waypoint; correctly calculates location of intermediate waypoints so target location will be the same as if the intervening waypoints had actually been executed
+	virtual void setTargetWaypoint(WaypointListIter_t iter) {
+		//cout << "Moving to waypoint " << iter << endl;
+		bool isLoop=false;
+		if(iter==waypoints.end()) {
+			if(isLooping && waypoints.size()>0) { //restart at beginning
+				iter=waypoints.begin();
+				for(unsigned int i=0; i<3; i++)
+					pathStartPos[i]=curPos[i];
+				isLoop=true;
+			} else { //not looping, halt
+				isRunning=false;
+				curWaypoint=iter;
+				for(unsigned int i=0; i<3; i++) {
+					sourcePos[i]=targetPos[i];
+					targetPos[i]=curPos[i];
+					curVel[i]=0;
+				}				
+				return;
+			}
+		}
+		if(iter==waypoints.next(curWaypoint) || isLoop)
+			for(unsigned int i=0; i<3; i++)
+				sourcePos[i]=targetPos[i];
+		else
+			for(unsigned int i=0; i<3; i++)
+				sourcePos[i]=curPos[i];
+
+		Waypoint target;
+		if(isLoop)
+			target=calcAbsoluteCoords(iter,pathStartPos[0],pathStartPos[1],pathStartPos[2]);
+		else
+			target=calcAbsoluteCoords(iter);
+		targetPos[0]=target.x;
+		targetPos[1]=target.y;
+		targetPos[2]=target.angle;
+
+		float dx=targetPos[0]-sourcePos[0];
+		float dy=targetPos[1]-sourcePos[1];
+		waypointDistance=sqrt(dx*dx+dy*dy);
+		waypointTime=get_time();
+		curWaypoint=iter;
+
+		float radiusRatio=sin(waypoints[iter].arc/2);
+		arcRadius = (radiusRatio==0) ? 0 : (waypointDistance/2)/radiusRatio;
+		pathLength = arcRadius!=0 ? arcRadius*waypoints[iter].arc : waypointDistance;
+
+		cout << "Target is now: ("<<targetPos[0]<<','<<targetPos[1]<<','<<targetPos[2]<<")" << endl;
+	}
+
+	//!if @a it follows the current waypoint, applies all the waypoints between #curWaypoint and @a it and returns result as an absolute position (angle field stores heading); otherwise calls the other calcAbsoluteCoords(WaypointListIter_t, float, float, float)
+	Waypoint calcAbsoluteCoords(WaypointListIter_t it) {
+		//find out if 'it' is coming up, or already passed
+		bool isAhead=false;
+		for(WaypointListIter_t c=curWaypoint; c!=waypoints.end(); c=waypoints.next(c))
+			if(c==it) {
+				isAhead=true;
+				break;
+			}
+		if(!isAhead)
+			return calcAbsoluteCoords(it,pathStartPos[0],pathStartPos[1],pathStartPos[2]);
+		Waypoint cur(targetPos[0],targetPos[1],Waypoint::POSTYPE_ABSOLUTE,targetPos[2],false,0,isTracking,turnSpeed);
+		if(it==curWaypoint)
+			return cur;
+		for(WaypointListIter_t c=waypoints.next(curWaypoint); c!=waypoints.end(); c=waypoints.next(c)) {
+			applyWaypoint(cur,waypoints[c]);
+			if(c==it)
+				break;
+		}
+		return cur;
+	}
+
+	//!starts at (@a sx, @a sy, heading=@a sa) and then applies all the waypoints up through @a it and returns result as an absolute position (angle field stores heading)
+	Waypoint calcAbsoluteCoords(WaypointListIter_t it,float sx, float sy, float sa) {
+		Waypoint cur(sx,sy,Waypoint::POSTYPE_ABSOLUTE,sa,false,0,isTracking,turnSpeed);
+		for(WaypointListIter_t c=waypoints.begin(); c!=waypoints.end(); c=waypoints.next(c)) {
+			applyWaypoint(cur,waypoints[c]);
+			if(c==it)
+				break;
+		}
+		return cur;
+	}
+
+
+protected:
+	void init(); //!< basic memory initialization
+
+	//!< if @a next is a relative waypoint (offset or egocentric), it is added to the location held in @a cur; otherwise if @a next is absolute, @a cur is set to @a next
+	/*! the Waypoint::angle field is used to store the headings */
+	void applyWaypoint(Waypoint& cur, const Waypoint& next); 
+
+	//! assumes the last waypoint is actually center of circle, adjusts it to be the endpoint of following @a arc radians around that circle instead
+	void fixArc(float arc);
+	
+	//! based on current velocity and time since last call, dead reckons current location in #curPos
+	/*! doesn't take acceleration into account, but should... :( */
+	void computeCurrentPosition(unsigned int t);
+	void checkNextWaypoint(unsigned int t);  //!< checks to see if #curPos is within #eps of #targetPos; if so, setTargetWaypoint() to next waypoint
+	void computeIdeal(unsigned int t);       //!< computes the ideal location (#idealPos) if we were following the intended path at the intended speed
+	void computeNewVelocity(unsigned int t); //!< computes the velocity which should be used given the current position (#curPos) relative to the ideal position (#idealPos)
+
+	//! will set a to be between (-pi,pi) (inclusive), just like atan2()
+	static float normalizeAngle(float a) {
+		while(a>M_PI)
+			a-=M_PI*2;
+		while(a<-M_PI)
+			a+=M_PI*2;
+		return a;
+	}
+
+	//! returns @a x such that it is at most @a max and at minimum @a min
+	static float clipRange(float x, float min, float max) {
+		if(x<min)
+			return min;
+		else if(x>max)
+			return max;
+		else
+			return x;
+	}
+
+	WaypointList_t waypoints; //!< storage for the waypoints
+
+	bool isRunning;  //!< true if we're currently executing the path
+	bool isLooping;  //!< true if we should loop when done
+	bool isTracking; //!< new waypoints will use trackPath mode
+	unsigned int curWaypoint;  //!< index of current waypoint
+	unsigned int waypointTime; //!< time we started working on current waypoint
+	float waypointDistance;    //!< distance from #sourcePos to #targetPos
+	float pathLength;          //!< distance to be traveled from #sourcePos to #targetPos (may differ from #waypointDistance due to arcing)
+	float arcRadius;           //!< radius of current arc, may be inf or NaN if using a straight line; can also be negative depending on direction!
+	unsigned int lastUpdateTime; //!< time we last updated curPos
+	float pathStartPos[3]; //!< position when started execution of current path (aka origin offset for relative positions which preceed an absolute waypoint)
+	float sourcePos[3]; //!< source position of the robot relative to the origin, aka absolute position of previous waypoint
+	float targetPos[3]; //!< target position of the robot relative to the origin, aka absolute position of next waypoint
+	float idealPos[4];  //!< ideal position of the robot relative to the origin, (x, y, heading, last element is desired direction of motion)
+	float curPos[3];    //!< current position of the robot relative to the origin
+	float curVel[3];    //!< current velocity
+	float eps[3];       //!< epsilon - "close enough" to register a hit on the waypoint
+	float Pcorr;        //!< proportional correction factor for tracking path
+	float turnSpeed;    //!< maximum turning speed for new waypoints
+};
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::go() {
+	isRunning=true;
+	for(unsigned int i=0; i<3; i++) {
+		curVel[i]=0;
+		pathStartPos[i]=sourcePos[i]=curPos[i];
+	}
+	Waypoint target(curPos[0],curPos[1],Waypoint::POSTYPE_ABSOLUTE,curPos[2],false,0,isTracking,turnSpeed);
+	applyWaypoint(target,waypoints.front());
+	targetPos[0]=target.x;
+	targetPos[1]=target.y;
+	targetPos[2]=target.angle;
+	lastUpdateTime=get_time();
+	curWaypoint=waypoints.begin();
+	setTargetWaypoint(curWaypoint);
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::pause() {
+	isRunning=false;
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::unpause() {
+	if(curWaypoint==waypoints.end())
+		go();
+	isRunning=true;
+	for(unsigned int i=0; i<3; i++)
+		curVel[i]=0;
+	lastUpdateTime=get_time();
+}
+
+template<unsigned int MAX_WAY>
+bool WaypointEngine<MAX_WAY>::cycle() {
+	if(!isRunning)
+		return false;
+	
+	unsigned int curtime=get_time();
+	if(curWaypoint!=waypoints.end()) {
+		computeCurrentPosition(curtime);
+		checkNextWaypoint(curtime);
+	}
+	if(curWaypoint!=waypoints.end()) {
+		computeIdeal(curtime);
+		computeNewVelocity(curtime);
+	}
+	
+	return true;
+}
+
+template<unsigned int MAX_WAY>
+unsigned int WaypointEngine<MAX_WAY>::getBinSize() const {
+	unsigned int numPrecision=9;
+	unsigned int wpSize=0;
+	unsigned int boilerplateSize=0;
+	boilerplateSize+=strlen("#WyP\n");
+	boilerplateSize+=strlen("#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val\n");
+	wpSize+=strlen("max_turn_speed ")+numPrecision+1;
+	wpSize+=strlen("track_path false\n");
+	wpSize+=strlen("add_point ")+4+numPrecision*5+1*5+strlen("follow");
+	boilerplateSize+=strlen("#END\n");
+	return wpSize*waypoints.size()+boilerplateSize;
+}
+
+template<unsigned int MAX_WAY>
+unsigned int WaypointEngine<MAX_WAY>::LoadBuffer(const char buf[], unsigned int len) {
+	unsigned int origlen=len;
+	waypoints.clear();
+	if(strncmp("#WyP\n",buf,5)!=0) {
+		return 0;
+	}
+
+	float turn=turnSpeed; //init to current mode, in case file doesn't specify
+	bool track=isTracking;
+	char cmd[40];
+	char posType[40];
+	float x_val=0;
+	float y_val=0;
+	char angType[40];
+	bool ang_val=0;
+	float angle_val=0;
+	float speed_val=0;
+	float arc_val=0;
+	unsigned int linenum=2;
+	while(len<=origlen && len>0) {
+		//		printf("%d %.9s\n",linenum+1,buf);
+		if(buf[0]=='#' || buf[0]=='\n') {
+			if(strncmp("#END\n",buf,5)==0)
+				return origlen-len;
+			else {
+				while(*buf++!='\n') {}
+				continue;
+			}
+		}
+		int used=-1U;
+		sscanf(buf,"%40s%n",&cmd,&used);
+		if(!ChkAdvance(used,&buf,&len,"*** ERROR Waypoint list load corrupted - ran out of room line %d\n",linenum)) return 0;
+		if(strncasecmp(cmd,"add_point",9)==0 || strncasecmp(cmd,"add_arc",7)==0) {
+			sscanf(buf,"%40s %g %g %40s %g %g %g%n",posType,&x_val,&y_val,angType,&angle_val,&speed_val,&arc_val,&used);
+			if(!ChkAdvance(used,&buf,&len,"*** ERROR Waypoint list load corrupted - bad read on add at line %d\n",linenum)) return 0;
+			if(strncasecmp(angType,"hold",4)==0)
+				ang_val=false;
+			else if(strncasecmp(angType,"follow",6)==0)
+				ang_val=true;
+			else {
+				printf("*** ERROR WaypointEngine: Invalid angle value type %s\n",angType);
+				return 0;
+			}
+			if(strncasecmp(cmd,"add_point",9)==0) {
+				if(strncasecmp(posType,"ego",3)==0)
+					addEgocentricWaypoint(x_val,y_val,angle_val,ang_val,speed_val);
+				else if(strncasecmp(posType,"off",3)==0)
+					addOffsetWaypoint(x_val,y_val,angle_val,ang_val,speed_val);
+				else if(strncasecmp(posType,"abs",3)==0)
+					addAbsoluteWaypoint(x_val,y_val,angle_val,ang_val,speed_val);
+				else {
+					printf("*** ERROR WaypointEngine: Invalid position type %s\n",posType);
+					return 0;
+				}						
+				waypoints.back().arc=arc_val;
+			} else {
+				if(strncasecmp(posType,"ego",3)==0)
+					addEgocentricArc(x_val,y_val,angle_val,ang_val,speed_val,arc_val);
+				else if(strncasecmp(posType,"off",3)==0)
+					addOffsetArc(x_val,y_val,angle_val,ang_val,speed_val,arc_val);
+				else if(strncasecmp(posType,"abs",3)==0)
+					addAbsoluteArc(x_val,y_val,angle_val,ang_val,speed_val,arc_val);
+				else {
+					printf("*** ERROR WaypointEngine: Invalid position type %s\n",posType);
+					return 0;
+				}
+			}
+			waypoints.back().trackPath=track;
+			waypoints.back().turnSpeed=turn;
+		} else if(strncasecmp(cmd,"track_path",10)==0) {
+			sscanf(buf,"%d%n",&track,&used);
+			if(!ChkAdvance(used,&buf,&len,"*** ERROR Waypoint load corrupted - bad read on track_path line %d\n",linenum)) return 0;
+		} else if(strncasecmp(cmd,"max_turn_speed",14)==0) {
+			sscanf(buf,"%g%n",&turn,&used);
+			if(!ChkAdvance(used,&buf,&len,"*** ERROR Waypoint load corrupted - bad read on max_turn_speed line %d\n",linenum)) return 0;
+		} else {
+			printf("*** ERROR WaypointEngine: Invalid command %s\n",cmd);
+			return 0;
+		}
+				
+		linenum++;
+	}
+	std::cout << "*** WARNING WaypointEngine: load missing #END" << std::endl;
+	return origlen-len;
+}
+
+template<unsigned int MAX_WAY>
+unsigned int WaypointEngine<MAX_WAY>::SaveBuffer(char buf[], unsigned int len) const {
+	unsigned int origLen=len;
+	unsigned int used;
+	unsigned int cnt=0;
+		
+	used=snprintf(buf,len,"#WyP\n");
+	if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on header\n")) return 0;
+
+	used=snprintf(buf,len,"#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val\n");
+	if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on header\n")) return 0;
+
+	//set our state variables so we'll be forced to output the first set
+	float turn=waypoints.front().turnSpeed-1;
+	bool track=!waypoints.front().trackPath;
+
+	for(WaypointListIter_t it=waypoints.begin(); it!=waypoints.end(); it=waypoints.next(it)) {
+		if(waypoints[it].turnSpeed!=turn) {
+			turn=waypoints[it].turnSpeed;
+			used=snprintf(buf,len,"max_turn_speed %g\n",turn);
+			if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on waypoint %d turnSpeed\n",cnt)) return 0;
+		}
+		if(waypoints[it].trackPath!=track) {
+			track=waypoints[it].trackPath;
+			used=snprintf(buf,len,"track_path %d\n",track);
+			if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on waypoint %d\n trackPath",cnt)) return 0;
+		}
+		const char * posType=NULL;
+		switch(waypoints[it].posType) {
+		case Waypoint::POSTYPE_EGOCENTRIC:
+			posType="EGO"; break;
+		case Waypoint::POSTYPE_OFFSET:
+			posType="OFF"; break;
+		case Waypoint::POSTYPE_ABSOLUTE:
+			posType="ABS"; break;
+		}
+		if(waypoints[it].arc!=0)
+			used=snprintf(buf,len,"add_point %s %g %g %s %g %g %g\n",posType,waypoints[it].x,waypoints[it].y,(waypoints[it].angleIsRelative?"FOLLOW":"HOLD"),waypoints[it].angle,waypoints[it].speed,waypoints[it].arc);
+		else //todo - store center of circle
+			used=snprintf(buf,len,"add_point %s %g %g %s %g %g %g\n",posType,waypoints[it].x,waypoints[it].y,(waypoints[it].angleIsRelative?"FOLLOW":"HOLD"),waypoints[it].angle,waypoints[it].speed,waypoints[it].arc);
+		if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on waypoint %d\n",cnt)) return 0;
+		cnt++;
+	}
+
+	used=snprintf(buf,len,"#END\n");
+	if(!ChkAdvance(used,(const char**)&buf,&len,"*** ERROR Waypoint list save failed on footer\n")) return 0;
+
+	return origLen-len;
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::init() {
+	eps[0]=eps[1]=.01; //1 centimeter
+	eps[2]=0.0175; //1 degree
+	for(unsigned int i=0; i<3; i++)
+		pathStartPos[i]=targetPos[i]=sourcePos[i]=curPos[i]=curVel[i]=0;
+	for(unsigned int i=0; i<4; i++)
+		idealPos[i]=0;
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::applyWaypoint(Waypoint& cur, const Waypoint& next) {
+	float origx=cur.x;
+	float origy=cur.y;
+	switch(next.posType) {
+	case Waypoint::POSTYPE_EGOCENTRIC: {
+		cur.x+=next.x*cos(cur.angle)-next.y*sin(cur.angle);
+		cur.y+=next.x*sin(cur.angle)+next.y*cos(cur.angle);
+		break;
+	}
+	case Waypoint::POSTYPE_OFFSET:
+		cur.x+=next.x;
+		cur.y+=next.y;
+		break;
+	case Waypoint::POSTYPE_ABSOLUTE:
+		cur.x=next.x;
+		cur.y=next.y;
+		break;
+	}
+	float dx=cur.x-origx;
+	float dy=cur.y-origy;
+	if(fabs(dx)<eps[0] && fabs(dy)<eps[1]) { //turn in place
+		if(next.angleIsRelative)
+			cur.angle+=next.angle;
+		else
+			cur.angle=next.angle;
+	} else { //move at heading
+		cur.angle=next.angle;
+		if(next.angleIsRelative)
+			cur.angle+=atan2(dy,dx);
+	}
+	cur.angle+=next.arc/2;
+	cur.angle=normalizeAngle(cur.angle);
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::fixArc(float arc) {
+	Waypoint& center=waypoints.back();
+	float cdx=center.x; //center delta
+	float cdy=center.y; //center delta
+	if(center.posType==Waypoint::POSTYPE_ABSOLUTE) {
+		//have to find location of waypoint before last one
+		WaypointListIter_t start_it=waypoints.prev(waypoints.prev(waypoints.end()));
+		if(start_it!=waypoints.end()) {
+			Waypoint start=calcAbsoluteCoords(waypoints.prev(waypoints.prev(waypoints.end())));
+			cdx-=start.x;
+			cdy-=start.y;
+		}
+	}
+	float r=sqrt(cdx*cdx+cdy*cdy); //radius of circle
+	float ca=atan2(cdy,cdx); //angle to center of circle
+	center.x-=r*cos(ca-arc); //now x is the endpoint
+	center.y-=r*sin(ca-arc); //now y is the endpoint
+	center.arc=arc;
+}
+	
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::computeCurrentPosition(unsigned int t) {
+	float dt=(t-lastUpdateTime)/1000.f;
+	float df=dt*curVel[0];
+	float ds=dt*curVel[1];
+	float da=dt*curVel[2];
+
+	float avgAngle=curPos[2]+da/2;
+	float ca=cos(avgAngle);
+	float sa=sin(avgAngle);
+
+	curPos[0]+=df*ca-ds*sa;
+	curPos[1]+=df*sa+ds*ca;
+	curPos[2]+=da;
+	curPos[2]=normalizeAngle(curPos[2]);
+
+	lastUpdateTime=t;
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::checkNextWaypoint(unsigned int /*t*/) {
+	float rx=targetPos[0]-curPos[0];
+	float ry=targetPos[1]-curPos[1];
+	float ra=targetPos[2]-curPos[2];
+	if(fabs(rx)<eps[0] && fabs(ry)<eps[1] && fabs(ra)<eps[2]) {
+		//cout << "Check succeeds: " << rx << ' '<<ry<<' ' << ra << endl;
+		setTargetWaypoint(waypoints.next(curWaypoint));
+	}
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::computeIdeal(unsigned int t) {
+	Waypoint& cur=waypoints[curWaypoint];
+	if(cur.trackPath) {
+		float dx=targetPos[0]-sourcePos[0];
+		float dy=targetPos[1]-sourcePos[1];
+		float dt=(t-waypointTime)/1000.f; //time we've been traveling towards current waypoint
+		float ideal_travel=dt*cur.speed; //distance we should have covered
+		float p=1; //will be set to percentage of path length to waypoint we have covered
+		if(pathLength!=0) {
+			p=ideal_travel/pathLength;
+			if(p>1)
+				p=1;
+		}
+		if(arcRadius==0) { //radius is "infinite" - straight line solution
+			idealPos[0]=sourcePos[0]+dx*p;
+			idealPos[1]=sourcePos[1]+dy*p;
+			idealPos[2]=targetPos[2];
+			idealPos[3]=atan2(dy,dx);
+		} else {
+			// have to find center of arc's circle
+			float bearing=atan2(dy,dx); //bearing of target from source
+			float center_bearing=bearing+(M_PI-cur.arc)/2; //bearing of center from source
+			float cx=sourcePos[0]+arcRadius*cos(center_bearing); //x pos of center
+			float cy=sourcePos[1]+arcRadius*sin(center_bearing); //y pos of center
+			float arc_bearing=center_bearing-M_PI+cur.arc*p; //bearing from center to current ideal location
+			//sout->printf("%g %g (%g,%g) %g\n",center_bearing,arcRadius,cx,cy,arc_bearing);
+			idealPos[0]=cx+arcRadius*cos(arc_bearing);
+			idealPos[1]=cy+arcRadius*sin(arc_bearing);
+			idealPos[3]=arc_bearing+M_PI/2;
+			idealPos[2]=cur.angle;
+			if(cur.angleIsRelative)
+				idealPos[2]+=idealPos[3];
+			idealPos[2]=normalizeAngle(idealPos[2]);
+			idealPos[3]=normalizeAngle(idealPos[3]);
+		}
+	} else {
+		idealPos[0]=curPos[0];
+		idealPos[1]=curPos[1];
+		float rx=targetPos[0]-curPos[0];
+		float ry=targetPos[1]-curPos[1];
+		if(fabs(rx)<eps[0] && fabs(ry)<eps[1]) {
+			idealPos[2]=targetPos[2];
+		} else {
+			idealPos[2]=cur.angle;
+			if(cur.angleIsRelative) {
+				float dx=targetPos[0]-curPos[0];
+				float dy=targetPos[1]-curPos[1];
+				idealPos[2]+=atan2(dy,dx);
+			}
+			idealPos[2]=normalizeAngle(idealPos[2]);
+		}
+		idealPos[3]=atan2(ry,rx);
+		if(arcRadius!=0) {
+			float dt=(t-waypointTime)/1000.f; //time we've been traveling towards current waypoint
+			float ideal_travel=dt*cur.speed; //distance we should have covered
+			float p=1; //will be set to percentage of path length to waypoint we have covered
+			if(pathLength!=0) {
+				p=ideal_travel/pathLength;
+				if(p>1)
+					p=1;
+			}
+			float arc=cur.arc*(1-p)/2;
+			idealPos[2]=normalizeAngle(idealPos[2]-arc);
+			idealPos[3]=normalizeAngle(idealPos[3]-arc);
+		}
+	}
+}
+
+template<unsigned int MAX_WAY>
+void WaypointEngine<MAX_WAY>::computeNewVelocity(unsigned int /*t*/) {
+	Waypoint& cur=waypoints[curWaypoint];
+
+	//first we'll start with the velocity we would use if we were on path
+	//determine distance remaining (only an approximation for arcing paths)
+	float dx=targetPos[0]-idealPos[0];
+	float dy=targetPos[1]-idealPos[1];
+	float spd=sqrt(dx*dx+dy*dy)/(FrameTime*NumFrames)*1000;
+	if(spd>cur.speed) {
+		//we're far away - go at full speed
+		curVel[0]=cur.speed*cos(idealPos[3]-curPos[2]);
+		curVel[1]=cur.speed*sin(idealPos[3]-curPos[2]);
+	} else {
+		//we're about to overshoot... just go fast enough to get on target
+		curVel[0]=spd*cos(idealPos[3]-curPos[2]);
+		curVel[1]=spd*sin(idealPos[3]-curPos[2]);
+	}
+	if(arcRadius==0)
+		curVel[2]=0;
+	else
+		curVel[2]=cur.speed/arcRadius;
+
+	//sout->printf("ideal vel: %g %g %g\n",curVel[0],curVel[1],curVel[2]);
+		
+	// then we'll add the errors
+	float ex=idealPos[0]-curPos[0];
+	float ey=idealPos[1]-curPos[1];
+	float ed=sqrt(ex*ex+ey*ey);
+	float ehead=atan2(ey,ex)-curPos[2];
+	float ea=normalizeAngle(idealPos[2]-curPos[2]);
+	float easpd=ea/(FrameTime*NumFrames)*1000;
+	easpd=clipRange(easpd,-cur.turnSpeed,cur.turnSpeed);
+	curVel[0]+=Pcorr*ed*cos(ehead);
+	curVel[1]+=Pcorr*ed*sin(ehead);
+	curVel[2]+=easpd;
+}
+
+/*! @file
+ * @brief Defines WaypointEngine, which provides computation and management of a desired path through a series of waypoints
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.4 $
+ * $State: Exp $
+ * $Date: 2004/07/27 14:33:59 $
+ */
+
+#endif
Index: Motion/WaypointWalkMC.h
===================================================================
RCS file: Motion/WaypointWalkMC.h
diff -N Motion/WaypointWalkMC.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/WaypointWalkMC.h	27 Jul 2004 14:33:59 -0000	1.3
@@ -0,0 +1,59 @@
+//-*-c++-*-
+#ifndef INCLUDED_WaypointWalk_h_
+#define INCLUDED_WaypointWalk_h_
+
+#include "Shared/ListMemBuf.h"
+#include "WalkMC.h"
+#include "WaypointEngine.h"
+
+//! Combines a WaypointEngine with a WalkMC so you can walk between a set of waypoints
+/*! Note the use of a template so we can have dedicate more or less
+ *  space without modifying the class.
+ *  
+ *  But for everyday use, you can just use the ::WaypointWalkMC typedef
+ *  which will default to a maximum of 100 waypoints */
+template<unsigned int MAX_WAY>
+class WaypointWalk : public WalkMC, public WaypointEngine<MAX_WAY> {
+public:
+	static const unsigned int MAX_WAYPOINTS=MAX_WAY; //!< for external access to maximum waypoints
+	
+	//!constructor
+	WaypointWalk()
+		: WalkMC(), WaypointEngine<MAX_WAYPOINTS>()
+	{}
+
+	//!constructor
+	WaypointWalk(char * f)
+		: WalkMC(), WaypointEngine<MAX_WAYPOINTS>(f)
+	{}
+	
+	//! so we can get our hooks in to modify the target velocity
+	virtual int updateOutputs() {
+		cycle();
+		WalkMC::setTargetVelocity(curVel[0]*1000,curVel[1]*1000,curVel[2]);
+		//cout << get_time()-waypointTime << " Cur: ("<<curPos[0]<<','<<curPos[1]<<','<<curPos[2]<<")  Ideal: ("<<idealPos[0]<<','<<idealPos[1]<<','<<idealPos[2]<<','<<idealPos[3]<<")  Vel: ("<<curVel[0]<<','<<curVel[1]<<','<<curVel[2]<<")" << endl;
+		return WalkMC::updateOutputs();
+	}
+
+	virtual int LoadWaypointFile(const char * f) { return WaypointEngine<MAX_WAYPOINTS>::LoadFile(f); } //!< allows loading a waypoint file
+	virtual int SaveWaypointFile(const char * f) const { return WaypointEngine<MAX_WAYPOINTS>::SaveFile(f); } //!< allows saving a waypoint file
+	virtual int LoadWalkMCFile(const char * f) { return WalkMC::LoadFile(f); } //!< allows loading a WalkMC parameter file
+	virtual int SaveWalkMCFile(const char * f) const { return WalkMC::SaveFile(f); } //!< allows saving a WalkMC parameter file
+
+};
+
+typedef WaypointWalk<100> WaypointWalkMC; //!< unless you need more/less waypoints, just use this type
+
+
+/*! @file
+ * @brief Defines WaypointWalk, which combines a WaypointEngine with a WalkMC so you can walk between a set of waypoints
+ * @author ejt (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.3 $
+ * $State: Exp $
+ * $Date: 2004/07/27 14:33:59 $
+ */
+
+#endif
Index: Motion/roboop/Makefile
===================================================================
RCS file: Motion/roboop/Makefile
diff -N Motion/roboop/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/Makefile	5 Oct 2004 04:40:50 -0000	1.8
@@ -0,0 +1,104 @@
+# Adapted from Makefile for Independent JPEG Group's software
+
+# This makefile is suitable for Unix-like systems with non-ANSI compilers.
+# If you have an ANSI compiler, makefile.ansi is a better starting point.
+
+# Read installation instructions before saying "make" !!
+
+# The name of your C compiler:
+OPENRSDK_ROOT ?= /usr/local/OPEN_R_SDK
+TEKKOTSU_ROOT ?= /usr/local/Tekkotsu
+CXX= $(OPENRSDK_ROOT)/bin/mipsel-linux-gcc
+
+# You may need to adjust these cc options:
+CXXFLAGS= -I ../../Shared/newmat -fno-inline \
+          -Wall -W -Wlarger-than-8192 -Wpointer-arith -Wcast-qual \
+          -Woverloaded-virtual -Wdeprecated -Wnon-virtual-dtor \
+          -O3 -frename-registers -fomit-frame-pointer -fno-common \
+
+#          -Wshadow -Weffc++
+
+# Link-time cc options:
+LDFLAGS=
+
+# To link any special libraries, add the necessary -l commands here.
+LDLIBS= 
+
+# miscellaneous OS-dependent stuff
+# linker
+LN= $(CC)
+# file deletion command
+RM= rm -f
+# file rename command
+MV= mv
+# library (.a) file creation command
+AR= $(OPENRSDK_ROOT)/bin/mipsel-linux-ar rc
+# second step in .a creation (use "touch" if not needed)
+AR2= $(OPENRSDK_ROOT)/bin/mipsel-linux-ranlib
+
+# End of configurable options.
+
+COLORFILT=$(TEKKOTSU_ROOT)/tools/colorfilt
+FILTERSYSWARN=$(TEKKOTSU_ROOT)/tools/filtersyswarn/filtersyswarn $(OPENRSDK_ROOT)
+
+# source files: JPEG library proper
+LIBSOURCES:= $(wildcard *.cpp)
+
+SOURCES= $(LIBSOURCES)
+
+LIBOBJECTS= $(LIBSOURCES:.cpp=.o)
+
+all: libroboop.a
+
+.PHONY: all clean
+
+libroboop.a: $(LIBOBJECTS)
+	$(RM) $@
+	$(AR) $@  $(LIBOBJECTS)
+	$(AR2) $@
+
+clean:
+	$(RM) *.o *.a *.log core
+
+%.o:
+	@echo "Compiling ROBOOP::$<... (Reduced warnings)"; \
+	$(CXX) $(CXXFLAGS) -o $@ -c $< > $*.log 2>&1; \
+	retval=$$?; \
+	cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+	test $$retval -eq 0; \
+
+controller.o: controller.cpp controller.h
+
+control_select.o: control_select.cpp control_select.h
+
+dynamics_sim.o: dynamics_sim.cpp dynamics_sim.h
+
+trajectory.o: trajectory.cpp trajectory.h
+
+clik.o :  clik.cpp clik.h utils.h robot.h
+
+robot.o :  robot.cpp utils.h robot.h
+
+config.o : config.cpp config.h
+
+quaternion.o : quaternion.cpp quaternion.h
+
+gnugraph.o :  gnugraph.cpp gnugraph.h utils.h robot.h
+
+comp_dq.o :  comp_dq.cpp utils.h robot.h
+
+comp_dqp.o :  comp_dqp.cpp utils.h robot.h
+
+delta_t.o :  delta_t.cpp utils.h robot.h
+
+dynamics.o :  dynamics.cpp utils.h robot.h
+
+homogen.o :  homogen.cpp utils.h robot.h
+
+invkine.o :  invkine.cpp utils.h robot.h
+
+kinemat.o :  kinemat.cpp utils.h robot.h
+
+sensitiv.o :  sensitiv.cpp utils.h robot.h
+
+utils.o :  utils.cpp utils.h robot.h
Index: Motion/roboop/clik.cpp
===================================================================
RCS file: Motion/roboop/clik.cpp
diff -N Motion/roboop/clik.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/clik.cpp	26 Sep 2004 19:55:35 -0000	1.5
@@ -0,0 +1,309 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: clik.cpp,v 1.5 2004/09/26 19:55:35 ejt Exp $";
+
+/*!
+  @file clik.cpp
+  @brief Clik member functions.
+*/
+
+#include "clik.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+/*!
+  @fn Clik::Clik(const Robot & robot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+                 const Real eps_, const Real lambda_max_, const Real dt);
+  @brief Constructor.
+*/
+Clik::Clik(const Robot & robot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+           const Real eps_, const Real lambda_max_, const Real dt_):
+      dt(dt_),
+      eps(eps_),
+      lambda_max(lambda_max_),
+      robot(robot_)
+{
+   robot_type = CLICK_DH;
+   // Initialize with same joint position (and rates) has the robot.
+   q = robot.get_q();
+   qp = robot.get_qp();
+   qp_prev = qp;
+   Kpep = ColumnVector(3); Kpep = 0;
+   Koe0Quat = ColumnVector(3); Koe0Quat = 0;
+   v = ColumnVector(6); v = 0;
+
+   if(Kp_.Nrows()==3)
+      Kp = Kp_;
+   else
+   {
+      Kp = DiagonalMatrix(3); Kp = 0.0;
+      cerr << "Clik::Clik-->Robot, Kp if not 3x3, set gain to 0." << endl;
+   }
+   if(Ko_.Nrows()==3)
+      Ko = Ko_;
+   else
+   {
+      Ko = DiagonalMatrix(3); Ko = 0.0;
+      cerr << "Clik::Clik-->Robot, Ko if not 3x3, set gain to 0." << endl;
+   }
+}
+
+
+/*!
+  @fn Clik::Clik(const mRobot & mrobot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+                 const Real eps_, const Real lambda_max_, const Real dt);
+  @brief Constructor.
+*/
+Clik::Clik(const mRobot & mrobot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+           const Real eps_, const Real lambda_max_, const Real dt_):
+      dt(dt_),
+      eps(eps_),
+      lambda_max(lambda_max_),
+      mrobot(mrobot_)
+{
+   robot_type = CLICK_mDH;
+   // Initialize with same joint position (and rates) has the robot.
+   q = mrobot.get_q();
+   qp = mrobot.get_qp();
+   qp_prev = qp;
+   Kpep = ColumnVector(3); Kpep = 0;
+   Koe0Quat = ColumnVector(3); Koe0Quat = 0;
+   v = ColumnVector(6); v = 0;
+
+   if(Kp_.Nrows()==3)
+      Kp = Kp_;
+   else
+   {
+      Kp = DiagonalMatrix(3); Kp = 0.0;
+      cerr << "Clik::Clik-->mRobot, Kp if not 3x3, set gain to 0." << endl;
+   }
+   if(Ko_.Nrows()==3)
+      Ko = Ko_;
+   else
+   {
+      Ko = DiagonalMatrix(3); Ko = 0.0;
+      cerr << "Clik::Cli, Ko if not 3x3, set gain to 0." << endl;
+   }
+}
+
+
+/*!
+  @fn Clik::Clik(const mRobot_min_para & mrobot_min_para_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+                 const Real eps_, const Real lambda_max_, const Real dt);
+  @brief Constructor.
+*/
+Clik::Clik(const mRobot_min_para & mrobot_min_para_, const DiagonalMatrix & Kp_,
+           const DiagonalMatrix & Ko_, const Real eps_, const Real lambda_max_,
+           const Real dt_):
+      dt(dt_),
+      eps(eps_),
+      lambda_max(lambda_max_),
+      mrobot_min_para(mrobot_min_para_)
+{
+   robot_type = CLICK_mDH_min_para;
+   // Initialize with same joint position (and rates) has the robot.
+   q = mrobot_min_para.get_q();
+   qp = mrobot_min_para.get_qp();
+   qp_prev = qp;
+   Kpep = ColumnVector(3); Kpep = 0;
+   Koe0Quat = ColumnVector(3); Koe0Quat = 0;
+   v = ColumnVector(6); v = 0;
+
+   if(Kp_.Nrows()==3)
+      Kp = Kp_;
+   else
+   {
+      Kp = DiagonalMatrix(3); Kp = 0.0;
+      cerr << "Clik::Clik-->mRobot, Kp if not 3x3, set gain to 0." << endl;
+   }
+   if(Ko_.Nrows()==3)
+      Ko = Ko_;
+   else
+   {
+      Ko = DiagonalMatrix(3); Ko = 0.0;
+      cerr << "Clik::Cli, Ko if not 3x3, set gain to 0." << endl;
+   }
+}
+
+
+Clik::Clik(const Clik & x)
+//!  @brief Copy constructor.
+{
+   robot_type = x.robot_type;
+   switch(robot_type)
+   {
+   case CLICK_DH:
+      robot = x.robot;
+      break;
+   case CLICK_mDH:
+      mrobot = x.mrobot;
+      break;
+   case CLICK_mDH_min_para:
+      mrobot_min_para = x.mrobot_min_para;
+      break;
+   }
+   eps = x.eps;
+   lambda_max = x.lambda_max;
+   dt = x.dt;
+   q = x.q;
+   qp = x.qp;
+   qp_prev = x.qp_prev;
+   Kpep = x.Kpep;
+   Koe0Quat = x.Koe0Quat;
+   Kp = x.Kp;
+   Ko = x.Ko;
+   v = x.v;
+}
+
+Clik & Clik::operator=(const Clik & x)
+//!  @brief Overload = operator.
+{
+   robot_type = x.robot_type;
+   switch(robot_type)
+   {
+   case CLICK_DH:
+      robot = x.robot;
+      break;
+   case CLICK_mDH:
+      mrobot = x.mrobot;
+      break;
+   case CLICK_mDH_min_para:
+      mrobot_min_para = x.mrobot_min_para;
+      break;
+   }
+   eps = x.eps;
+   lambda_max = x.lambda_max;
+   dt = x.dt;
+   q = x.q;
+   qp = x.qp;
+   qp_prev = x.qp_prev;
+   Kpep = x.Kpep;
+   Koe0Quat = x.Koe0Quat;
+   Kp = x.Kp;
+   Ko = x.Ko;
+   v = x.v;
+
+   return *this;
+}
+
+
+int Clik::endeff_pos_ori_err(const ColumnVector & pd, const ColumnVector & /*pdd*/,
+                             const Quaternion & qqqd, const ColumnVector & /*wd*/)
+/*!
+  @brief Obtain end effector position and orientation error.
+  @param pd: Desired eff position in base frame.
+  @param pdd: Desired eff velocity in base frame. (unused)
+  @param qqqd: Desired eff orientation in base frame.
+  @param wd: Desired eff angular velocity in base frame. (unused)
+*/
+{
+   ColumnVector p;
+   Matrix R;
+
+   switch(robot_type)
+   {
+   case CLICK_DH:
+      robot.set_q(q);
+      robot.kine(R, p);  // In base frame
+      break;
+   case CLICK_mDH:
+      mrobot.set_q(q);
+      mrobot.kine(R, p);
+      break;
+   case CLICK_mDH_min_para:
+      mrobot_min_para.set_q(q);
+      mrobot_min_para.kine(R, p);
+      break;
+   }
+   Kpep = Kp*(pd - p);
+   Quaternion qq(R);
+
+   Quaternion qqd;
+
+   if(qq.dot_prod(qqqd) < 0)
+      qqd = qqqd*(-1);
+   else
+      qqd = qqqd;
+
+   // quaternion error on vectoriel part. We used equation 42 [4] instead equation 23 [1].
+   Koe0Quat = Ko*(qq.s()*qqd.v() - qqd.s()*qq.v() + x_prod_matrix(qq.v())*qqd.v());
+
+   return 0;
+}
+
+
+void Clik::q_qdot(const Quaternion & qd, const ColumnVector & pd,
+                  const ColumnVector & pdd, const ColumnVector & wd,
+                  ColumnVector & q_, ColumnVector & qp_)
+/*!
+  @brief Obtain joints position and velocity.
+  @param qd: Desired eff orientatio in base frame.
+  @param pd: Desired eff position in base frame.
+  @param pdd: Desired eff velocity in base frame.
+  @param wd: Desired eff angular velocity in base frame.
+  @param q_: Output joint position.
+  @param qp_: Output joint velocity.
+*/
+{
+   v.SubMatrix(1,3,1,1) = pdd + Kpep;
+   v.SubMatrix(4,6,1,1) = wd + Koe0Quat;
+
+   switch(robot_type)
+   {
+   case CLICK_DH:
+      robot.set_q(q);
+      qp = robot.jacobian_DLS_inv(eps, lambda_max)*v;
+      break;
+   case CLICK_mDH:
+      mrobot.set_q(q);
+      qp = mrobot.jacobian_DLS_inv(eps, lambda_max)*v;
+      break;
+   case CLICK_mDH_min_para:
+      mrobot_min_para.set_q(q);
+      qp = mrobot_min_para.jacobian_DLS_inv(eps, lambda_max)*v;
+      break;
+   }
+
+   q = q + Integ_Trap(qp, qp_prev, dt);
+   endeff_pos_ori_err(pd, pdd, qd, wd);
+
+   q_ = q;
+   qp_ = qp;
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/clik.h
===================================================================
RCS file: Motion/roboop/clik.h
diff -N Motion/roboop/clik.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/clik.h	14 Jul 2004 02:32:11 -0000	1.4
@@ -0,0 +1,128 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+Reference:
+
+CLIK: closed loop inverse kinematics
+
+[1] S. Chiaverini, B. Siciliano, "The Unit Quaternion: A Useful Tool for
+    Inverse Kinematics of Robot Manipulators", Systems Analysis, Modelling
+    and Simulation, vol. 35, pp.45-60, 1999.
+
+[2] F. Caccavale, S. Chiaverini, B. Siciliano, "Second-Order Kinematic Control 
+    of Robot Manipulators with Jacobian Damped Least-Squares Inverse: Theory
+    and Experiments", IEEE/ASME Trans on Mechatronics, vol 2, no. 3, 
+    pp. 188-194, 1997.
+
+[3] S. Chiaverini, B. Siciliano, "Review of the Damped Least-Squares Inverse 
+    Kinematics with Experiments on an Industrial Robot Manipulator" IEEE Trans
+    on Control Systems Technology, vol 2, no 2, june 1994
+
+[4] C. Natale, "Quaternion-Based Representation of Rigid Bodies Orientation",
+    PRISMA LAB, PRISMA Technical Report no. 97-05, Oct 1997.
+
+The algorithme is based on [1], which is of first order.     
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+*/
+
+
+#ifndef CLIK_H
+#define CLIK_H
+
+/*!
+  @file clik.h
+  @brief Header file for Clik class definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_clik_rcsid[] = "$Id: clik.h,v 1.4 2004/07/14 02:32:11 ejt Exp $";
+
+#include "robot.h"
+#include "quaternion.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+//! @brief Using Clik under DH notation.
+#define CLICK_DH           1
+//! @brief Using Clik under modified DH notation.
+#define CLICK_mDH          2
+//! @brief Using Clik under modified DH notation with minimum intertial parameters
+#define CLICK_mDH_min_para 3
+
+
+//! @brief Handle Closed Loop Inverse Kinematics scheme.
+class Clik {
+public:
+   Clik(){}
+   Clik(const Robot & robot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+        const Real eps_=0.04, const Real lambda_max_=0.04, const Real dt=1.0);
+   Clik(const mRobot & mrobot_, const DiagonalMatrix & Kp_, const DiagonalMatrix & Ko_,
+        const Real eps_=0.04, const Real lambda_max_=0.04, const Real dt=1.0);
+   Clik(const mRobot_min_para & mrobot_min_para_, const DiagonalMatrix & Kp_,
+        const DiagonalMatrix & Ko_, const Real eps_=0.04, const Real lambda_max_=0.04,
+        const Real dt=1.0);
+   Clik(const Clik & x);
+   ~Clik(){}
+   Clik & operator=(const Clik & x);
+   void q_qdot(const Quaternion & qd, const ColumnVector & pd,
+               const ColumnVector & pddot, const ColumnVector & wd,
+               ColumnVector & q, ColumnVector & qp);
+private:
+   int endeff_pos_ori_err(const ColumnVector & pd, const ColumnVector & pddot,
+                          const Quaternion & qd, const ColumnVector & wd);
+
+   Real 
+     dt,                //!< Time frame.
+     eps,               //!< Range of singular region in Jacobian DLS inverse.
+     lambda_max;        //!< Damping factor in Jacobian DLS inverse.
+   short  robot_type;   //!< Robot type used.
+   Robot robot;         //!< Robot instance.
+   mRobot mrobot;       //!< mRobot instance.
+   mRobot_min_para mrobot_min_para; //!< mRobot_min_para instance.
+   DiagonalMatrix Kp,   //!< Position error gain.
+                  Ko;   //!< Orientation error gain.
+
+   ColumnVector q ,       //!< Clik joint position.
+                qp,       //!< Clik joint velocity.
+                qp_prev,  //!< Clik previous joint velocity.
+                Kpep,     //!< Kp times position error.
+                Koe0Quat, //!< Ko times orientation error (quaternion vector part).
+                v;        //!< Quaternion vector part.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
Index: Motion/roboop/comp_dq.cpp
===================================================================
RCS file: Motion/roboop/comp_dq.cpp
diff -N Motion/roboop/comp_dq.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/comp_dq.cpp	14 Jul 2004 02:32:11 -0000	1.4
@@ -0,0 +1,463 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/14/05: Etienne Lachance
+   -Fix Robot::dq_torque.
+   -Added mRobot/mRobot_min_para::dq_torque.
+
+2004/07/01: Etienne Lachance
+   -Replace vec_x_prod by CrossProduct.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+   -Added Doxygen comments.
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file comp_dq.cpp
+  @brief Delta torque (linearized dynamics).
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: comp_dq.cpp,v 1.4 2004/07/14 02:32:11 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+void Robot::dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                      const ColumnVector & qpp, const ColumnVector & dq,
+                      ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint position.
+
+  This function computes \f$S_2(q, \dot{q}, \ddot{q})\delta q\f$.
+  See Robot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || qpp.Nrows() != dof) error("dq has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0;  z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = ColumnVector(3);
+      p[i](1) = links[i].get_a();
+      p[i](2) = links[i].get_d() * Rt(2,3);
+      p[i](3) = links[i].get_d() * Rt(3,3);
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*(w[i-1] + z0*qp(i));
+         dw[i] = Rt*(dw[i-1] - Q*w[i-1]*dq(i));
+         wp[i] = Rt*(wp[i-1] + z0*qpp(i)
+                     + CrossProduct(w[i-1],z0*qp(i)));
+         dwp[i] = Rt*(dwp[i-1]
+                      + CrossProduct(dw[i-1],z0*qp(i))
+                      - Q*(wp[i-1]+z0*qpp(i)+CrossProduct(w[i-1],z0*qp(i)))
+                      *dq(i));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]))
+                 + Rt*(vp[i-1]);
+         dvp[i] = CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]))
+                  + Rt*(dvp[i-1] - Q*vp[i-1]*dq(i));
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + z0*qpp(i)
+                     + 2.0*CrossProduct(w[i],Rt*z0*qp(i)))
+                 + CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]));
+         dvp[i] = Rt*(dvp[i-1]
+                      + 2.0*CrossProduct(dw[i-1],z0*qp(i)))
+                  + CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]))
+                  + (CrossProduct(wp[i],dp[i])
+                     + CrossProduct(w[i],CrossProduct(w[i],dp[i])))
+                  *dq(i);
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dF[i] = da[i] * links[i].m;
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i].get_joint_type() != 0)
+            dn[i] += CrossProduct(dp[i],f[i])*dq(i);
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i+1].get_joint_type() == 0)
+            df[i] += Q*links[i+1].R*f[i+1]*dq(i+1);
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i+1].get_joint_type() == 0)
+            dn[i] += Q*links[i+1].R*n[i+1]*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i],f[i])*dq(i);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = ((z0.t()*links[i].R)*n[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*dn[i]);
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = ((z0.t()*links[i].R)*f[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*df[i]);
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+
+void mRobot::dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                       const ColumnVector & qpp, const ColumnVector & dq,
+                       ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint position.
+
+  This function computes \f$S_2(q, \dot{q}, \ddot{q})\delta q\f$.
+  See mRobot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || dq.Nrows() != dof) error("dq has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] - Q*Rt*w[i-1]*dq(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i))
+                 + z0*qpp(i);
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i))
+                  - (Q*Rt*wp[i-1] + CrossProduct(Q*Rt*w[i-1],z0*qp(i)))*dq(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  - Q*Rt*(CrossProduct(wp[i-1],p[i])
+                          + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])) + vp[i-1])*dq(i);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i)+ 2.0*CrossProduct(w[i],z0*qp(i));
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]
+                      + (CrossProduct(wp[i-1],dp[i])
+                         + CrossProduct(w[i-1],CrossProduct(w[i-1],dp[i])))*dq(i))
+                  + 2*CrossProduct(dw[i],z0*qp(i));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dF[i] = da[i] * links[i].m;
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = dN[i] + CrossProduct(links[i].r,dF[i]);
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i+1].get_joint_type() == 0)
+            df[i] += links[i+1].R*Q*f[i+1]*dq(i+1);
+
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i+1].get_joint_type() == 0)
+            dn[i] += (links[i+1].R*Q*n[i+1] +
+                      CrossProduct(p[i+1],links[i+1].R*Q*f[i+1]))*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i+1],links[i+1].R*f[i+1])*dq(i+1);
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+
+void mRobot_min_para::dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                                const ColumnVector & qpp, const ColumnVector & dq,
+                                ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint position.
+
+  This function computes \f$S_2(q, \dot{q}, \ddot{q})\delta q\f$.
+  See mRobot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || dq.Nrows() != dof) error("dq has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] - Q*Rt*w[i-1]*dq(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i))
+                 + z0*qpp(i);
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i))
+                  - (Q*Rt*wp[i-1] + CrossProduct(Q*Rt*w[i-1],z0*qp(i)))*dq(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  - Q*Rt*(CrossProduct(wp[i-1],p[i])
+                          + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])) + vp[i-1])*dq(i);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i)+ 2.0*CrossProduct(w[i],z0*qp(i));
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]
+                      + (CrossProduct(wp[i-1],dp[i])
+                         + CrossProduct(w[i-1],CrossProduct(w[i-1],dp[i])))*dq(i));
+      }
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc) +
+             CrossProduct(w[i], CrossProduct(w[i], links[i].mc));
+      dF[i] = dvp[i]*links[i].m + CrossProduct(dwp[i],links[i].mc)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].mc))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].mc));
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i])
+             - CrossProduct(vp[i], links[i].mc);
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i])
+              - CrossProduct(dvp[i],links[i].mc);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = N[i];
+         dn[i] = dN[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i+1].get_joint_type() == 0)
+            df[i] += links[i+1].R*Q*f[i+1]*dq(i+1);
+
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1])
+                 + dN[i];
+         if(links[i+1].get_joint_type() == 0)
+            dn[i] += (links[i+1].R*Q*n[i+1] +
+                      CrossProduct(p[i+1],links[i+1].R*Q*f[i+1]))*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i+1],links[i+1].R*f[i+1])*dq(i+1);
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/comp_dqp.cpp
===================================================================
RCS file: Motion/roboop/comp_dqp.cpp
diff -N Motion/roboop/comp_dqp.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/comp_dqp.cpp	14 Jul 2004 02:32:11 -0000	1.4
@@ -0,0 +1,426 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/14/05: Etienne Lachance
+   -Added function mRobot/mRobot_min_para::dqp_torque
+
+2004/07/01: Etienne Lachance
+   -Replaced vec_x_prod by CrossProduct.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+    -Added Doxygen comments.
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file comp_dqp.cpp
+  @brief Delta torque (linearized dynamics).
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: comp_dqp.cpp,v 1.4 2004/07/14 02:32:11 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+void Robot::dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                       const ColumnVector & dqp,
+                       ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint velocity.
+
+  This function computes \f$S_1(q, \dot{q}, \ddot{q})\delta \dot{q}\f$.
+  See Robot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(dqp.Ncols() != 1 || qp.Nrows() != dof) error("dqp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0;  z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = ColumnVector(3);
+      p[i](1) = links[i].get_a();
+      p[i](2) = links[i].get_d() * Rt(2,3);
+      p[i](3) = links[i].get_d() * Rt(3,3);
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*(w[i-1] + z0*qp(i));
+         dw[i] = Rt*(dw[i-1] + z0*dqp(i));
+         wp[i] = Rt*(wp[i-1] + CrossProduct(w[i-1],z0*qp(i)));
+         dwp[i] = Rt*(dwp[i-1]
+                      + CrossProduct(dw[i-1],z0*qp(i))
+                      + CrossProduct(w[i-1],z0*dqp(i)));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]))
+                 + Rt*(vp[i-1]);
+         dvp[i] = CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]))
+                  + Rt*dvp[i-1];
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1]
+                     + 2.0*CrossProduct(w[i],Rt*z0*qp(i)))
+                 + CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]));
+         dvp[i] = Rt*(dvp[i-1]
+                      + 2.0*(CrossProduct(dw[i-1],z0*qp(i))
+                             + CrossProduct(w[i-1],z0*dqp(i))))
+                  + CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dF[i] = da[i] * links[i].m;
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+      if(i == dof)
+      {
+         f[i] = F[i];
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         df[i] = dF[i];
+         dn[i] = CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = ((z0.t()*links[i].R)*n[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*dn[i]);
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = ((z0.t()*links[i].R)*f[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*df[i]);
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+void mRobot::dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                        const ColumnVector & dqp, ColumnVector & ltorque,
+                        ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint velocity.
+
+  This function computes \f$S_1(q, \dot{q}, \ddot{q})\delta \dot{q}\f$.
+  See mRobot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(dqp.Ncols() != 1 || dqp.Nrows() != dof) error("dqp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] + z0*dqp(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i));
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i))
+                  + CrossProduct(Rt*w[i-1],z0*dqp(i));
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + 2.0*CrossProduct(w[i],z0*qp(i));
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  + 2*(CrossProduct(dw[i],z0*qp(i)) + CrossProduct(w[i],z0*dqp(i)));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dF[i] = da[i] * links[i].m;
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = dN[i] + CrossProduct(links[i].r,dF[i]);
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+void mRobot_min_para::dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                                 const ColumnVector & dqp, ColumnVector & ltorque,
+                                 ColumnVector & dtorque)
+/*!
+  @brief Delta torque due to delta joint velocity.
+
+  This function computes \f$S_1(q, \dot{q}, \ddot{q})\delta \dot{q}\f$.
+  See mRobot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(dqp.Ncols() != 1 || dqp.Nrows() != dof) error("dqp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] + z0*dqp(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i));
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i));
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + 2.0*CrossProduct(w[i],z0*qp(i));
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  + 2*(CrossProduct(dw[i],z0*qp(i)) + CrossProduct(w[i],z0*dqp(i)));
+      }
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc) +
+             CrossProduct(w[i], CrossProduct(w[i], links[i].mc));
+      dF[i] = dvp[i]*links[i].m + CrossProduct(dwp[i],links[i].mc)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].mc))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].mc));
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i])
+             - CrossProduct(vp[i], links[i].mc);
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i])
+              - CrossProduct(dvp[i],links[i].mc);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = N[i];
+         dn[i] = dN[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1]) + dN[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/config.cpp
===================================================================
RCS file: Motion/roboop/config.cpp
diff -N Motion/roboop/config.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/config.cpp	1 Sep 2004 19:51:04 -0000	1.9
@@ -0,0 +1,634 @@
+/*
+Copyright (C) 2003-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polytml.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/06/10: Etienne Lachance
+    -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/13: Ethan Tira-Thompson
+    -Added a select_real and add_real function for type indepence of Real
+    -Added functions to test for sections and parameters existance
+
+2004/07/23: Ethan Tira-Thompson
+    -Fixed potentially uninitialized variables and some other warnings
+
+2004/09/01: Ethan Tira-Thompson
+    -Added optional parameter to constructor so you can automatically read_conf
+    -select_* functions are now const
+-------------------------------------------------------------------------------
+*/
+
+/*! 
+  @file config.cpp
+  @brief Configuration class functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: config.cpp,v 1.9 2004/09/01 19:51:04 ejt Exp $";
+
+
+#include "config.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+Config::Config(const string & filename_, bool doRead/*=false*/)
+//! @brief Constructor.
+	: conf(), filename(filename_)
+{
+   if(doRead)
+      read_conf();
+}
+
+Config::Config(const Config & x)
+//! @brief Constructor.
+	: conf(x.conf), filename(x.filename)
+{
+}
+
+Config & Config::operator=(const Config & x)
+//! @brief Overload = operator.
+{
+   conf = x.conf;
+   filename = x.filename;
+   return *this;
+}
+
+short Config::read_conf()
+/*!
+  @brief Read a configuration file.
+
+  This function reads the configuration file specified in 
+  the constructor parameter. The information is stored in the
+  variable conf.
+
+  A configuration file contains section(s) (between [ ]), and the 
+  section(s) contains parameter(s) with there respective value(s). 
+  The section and the parameter are always access via a string. Below 
+  is an exemple: one section named PUMA560_mDH, and two parameters.
+
+  [PUMA560_mDH]
+  DH:         0
+  dof:        6
+*/
+{
+   const char *ptr_filename = filename.c_str(); //transform string to *char
+
+   std::ifstream inconffile(ptr_filename, std::ios::in);
+
+   if(inconffile)
+   {
+      string temp;
+      int tmpPos;
+      Data data;
+#ifdef __WATCOMC__
+      char tempo[256], tempo2[256];
+      string section, parameter, value;
+      inconffile.getline(tempo,sizeof(tempo));
+      temp = tempo;
+#else
+      getline(inconffile, temp);
+#endif
+
+      while( !inconffile.eof() )
+      {
+	 // Is-it comment line?
+         if(temp.substr(0,1) != "#")
+         {
+	    // Is-it a section name?
+            if(temp.substr(0,1) == "[") // [section]
+            {
+	       // Search for the end of the section name and ignore the rest of the line.
+ 	       tmpPos = temp.find("]");
+	       if (tmpPos != (int)string::npos)
+		 {
+		   data.section = temp.substr(1, tmpPos-1); // remove []
+		   // Read the next line, it's should be a parameter.
+#ifdef __WATCOMC__
+		   inconffile.getline(tempo,sizeof(tempo));
+		   temp = tempo;
+#else
+		   getline(inconffile, temp);
+#endif
+		   // Be sure that is not another section name.
+		   while( (temp.substr(0,1) != "[") &&
+			  (!inconffile.eof()) )
+		     {
+		       if(temp.substr(0,1) != "#") // ignore comments
+			 {
+			   if(temp.find(":") != string::npos)
+			     {
+#ifdef __WATCOMC__
+			       istrstream inputString(tempo);
+			       inputString >> tempo2;
+			       data.parameter = tempo2;
+			       inputString >> tempo2;
+			       data.value = tempo2;
+#else
+			       istringstream inputString(temp);
+			       inputString >> data.parameter >> data.value;
+#endif
+			       // Find ":" in parameter.
+			       tmpPos = data.parameter.find(":");
+			       if (tmpPos != (int)string::npos)
+				 // remove ":" a the end of parameter
+				 data.parameter = data.parameter.substr(0, tmpPos);
+			       else
+				 {
+#ifdef __WATCOMC__
+				   inputString >> tempo2;
+				   data.value = tempo2;
+#else
+				   inputString >> data.value;
+#endif
+				 }
+
+			       // Add data to the config vector
+			       conf.push_back(data);
+			     }
+
+			   // Read the next line.
+#ifdef __WATCOMC__
+			   inconffile.getline(tempo,sizeof(tempo));
+			   temp = tempo;
+#else
+			   getline(inconffile, temp);
+#endif
+			 }
+		       else
+			 {
+			   // Ignore comments and read the next line.
+#ifdef __WATCOMC__
+			   inconffile.getline(tempo,sizeof(tempo));
+			   temp = tempo;
+#else
+			   getline(inconffile, temp);
+#endif
+			 }
+		     }
+		 }
+            }
+         }
+         if(temp.substr(0,1) != "[") {
+#ifdef __WATCOMC__
+            inconffile.getline(tempo,sizeof(tempo));
+            temp = tempo;
+#else
+            getline(inconffile, temp);
+#endif
+         }
+      }
+   }
+   else
+   {
+      cerr << "Config::read_conf: can not open file " << filename.c_str() << endl;
+      return CAN_NOT_OPEN_FILE;
+   }
+   return 0;
+}
+
+void Config::print()
+//! @brief Print the configuration data.
+{
+  string tmpSection;
+  for(Conf_data::iterator iter = conf.begin(); iter != conf.end(); ++iter)
+    {
+      if (tmpSection != iter->section)
+	{
+	  //Beginning of a section
+	  tmpSection = iter->section;
+	  cout << "\n[" << tmpSection << "]" << endl;
+	}
+      else
+	  cout << setw(15-iter->parameter.size()) << iter->parameter+":" << " " 
+	       << iter->value << endl;
+    }
+}
+
+bool Config::section_exists(const string& section) const
+/*!
+  @brief Test to see if a section exists
+  @return true if @a section is found
+*/
+{
+	for(Conf_data::const_iterator iter = conf.begin(); iter != conf.end(); ++iter)
+		if(iter->section == section)
+			return true;
+	return false;
+}
+
+bool Config::parameter_exists(const string& section, const string& parameter) const
+/*!
+  @brief Test to see if a parameter exists within a section
+  @return true if @a parameter is found within @a section
+*/
+{
+	for(Conf_data::const_iterator iter = conf.begin(); iter != conf.end(); ++iter)
+		if( (iter->section == section) && (iter->parameter == parameter) )
+			return true;
+	return false;
+}
+
+short Config::select_string(const string section, const string parameter, string & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the string value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   for(Conf_data::const_iterator iter = conf.begin(); iter != conf.end(); ++iter)
+   {
+      if( (iter->section == section) && (iter->parameter == parameter) )
+      {
+         value = iter->value;
+         return 0;
+      }
+   }
+   value = "";
+   cerr << "Config::select_string: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist." << endl;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_bool(const string section, const string parameter, bool & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the bool value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      value = istr;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_bool: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = false;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_int(const string section, const string parameter, int & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the int value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      istr >> value;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_int: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = 0;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_short(const string section, const string parameter, short & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the short value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      istr >> value;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_short: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = 0;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_float(const string section, const string parameter, float & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the float value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      istr >> value;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_float: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = 0.0;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_double(const string section, const string parameter, double & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the double value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      istr >> value;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_double: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = 0.0;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::select_real(const string section, const string parameter, Real & value) const
+/*!
+  @brief Get a parameter data, of a certain section, into the Real value.
+  @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
+*/
+{
+   string value_string;
+   if(!select_string(section, parameter, value_string))
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+      strcpy(temp,value_string.c_str());
+      istrstream istr(temp);
+      istr >> value;
+#else
+      istringstream istr(value_string);
+      istr >> value;
+#endif
+      return 0;
+   }
+   cerr << "Config::select_real: section " << section.c_str() << " or parameter "
+   << parameter.c_str() << " does not exist" << endl;
+   value = 0.0;
+   return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
+}
+
+short Config::write_conf(const string name, const string file_title,
+                         const int space_between_column)
+/*!
+  @brief Write the configuration information, contained in conf, on disk.
+  @param name: Configuration file name.
+  @param file_title: Title in the configuration file header.
+  @param space_between_column: Number of blanks between : (of a parameter) and it's value.
+*/
+{
+   const char *ptr_filename = name.c_str(); //transform string to *char
+   std::ofstream outconffile(ptr_filename, std::ios::out);
+
+   if(outconffile)
+   {                     // file header
+      outconffile << "# ---------------------------------------------------" << endl;
+      outconffile << "# " << file_title << endl;
+      outconffile << "# ---------------------------------------------------" << endl;
+      outconffile << endl;
+
+      string section = "";
+
+      for(Conf_data::iterator iterConf = conf.begin(); iterConf != conf.end(); ++iterConf)
+      {
+         if(section != iterConf->section)
+         {
+            section = iterConf->section;
+            outconffile << "\n[" << section << "]\n" << endl;
+         }
+	 outconffile << setw(space_between_column-iterConf->parameter.size()) 
+		     << iterConf->parameter + ":" << " " << iterConf->value << endl;
+      }
+      return 0;
+   }
+   else
+   {
+      cerr << "Config::write_conf: can not create file " << name.c_str() << endl;
+      return CAN_NOT_CREATE_FILE;
+   }
+}
+
+void Config::add_string(const string section, const string parameter, const string value)
+/*!
+  @brief Added the value(string) of the parameter in the section in the configuration data.
+
+  The functions will added the parameter and the section if it does not already exist.
+*/
+{
+   Data dataSet;
+   dataSet.section = section;
+   dataSet.parameter = parameter;
+   dataSet.value = value;
+   for(Conf_data::iterator iterConf = conf.begin(); iterConf != conf.end(); ++iterConf)
+   {
+      if(section == iterConf->section) // section already exist
+      {
+         if(parameter == iterConf->parameter) // parameter already exist
+         {
+            iterConf->value = value;
+            return;
+         }
+         // parameter does not exist
+         for(Conf_data::iterator iterConf2 = iterConf; iterConf2 != conf.end(); ++iterConf2)
+         {
+            if(section != iterConf2->section)
+            {
+               conf.insert(iterConf2, dataSet);
+               return;
+            }
+         }
+      }
+   }
+   // section and parameter does not exist.
+   conf.push_back(dataSet);
+}
+
+void Config::add_bool(const string section, const string parameter,
+                      const bool value)
+/*!
+  @brief Added the value (bool) of the parameter in the section in the configuration data.
+
+  The functions use add_string by first converting the value (bool) in value (string) 
+*/
+{
+   string value_tmp;
+#ifdef __WATCOMC__
+   ostrstream ostr;
+#else
+   ostringstream ostr;
+#endif
+   ostr << value;
+   value_tmp = ostr.str();
+
+   add_string(section, parameter, value_tmp);
+}
+
+void Config::add_int(const string section, const string parameter,
+                     const int value)
+/*!
+  @brief Added the value (int) of the parameter in the section in the configuration data.
+
+  The functions use add_string by first converting the value (int) in value (string) 
+*/
+{
+   string value_tmp;
+#ifdef __WATCOMC__
+   ostrstream ostr;
+#else
+   ostringstream ostr;
+#endif
+   ostr << value;
+   value_tmp = ostr.str();
+
+   add_string(section, parameter, value_tmp);
+}
+
+void Config::add_float(const string section, const string parameter,
+		       const float value)
+/*!
+  @brief Added the value (float) of the parameter in the section in the configuration data.
+
+  The functions use add_string by first converting the value (float) in value (string) 
+*/
+{
+   string value_tmp;
+#ifdef __WATCOMC__
+   ostrstream ostr;
+#else
+   ostringstream ostr;
+#endif
+#ifdef _MSC_VER  
+   ostr << value; // need to be fixed !
+#else
+   ostr << setprecision(13) << value;
+#endif
+   value_tmp = ostr.str();
+
+   add_string(section, parameter, value_tmp);
+}
+
+void Config::add_double(const string section, const string parameter,
+                        const double value)
+/*!
+  @brief Added the value (double) of the parameter in the section in the configuration data.
+
+  The functions use add_string by first converting the value (double) in value (string) 
+*/
+{
+   string value_tmp;
+#ifdef __WATCOMC__
+   ostrstream ostr;
+#else
+   ostringstream ostr;
+#endif
+#ifdef _MSC_VER  
+   ostr << value; // need to be fixed !
+#else
+   ostr << setprecision(13) << value;
+#endif
+   value_tmp = ostr.str();
+
+   add_string(section, parameter, value_tmp);
+}
+
+void Config::add_real(const string section, const string parameter,
+                        const Real value)
+/*!
+  @brief Added the value (Real) of the parameter in the section in the configuration data.
+
+  The functions use add_string by first converting the value (Real) in value (string) 
+*/
+{
+   string value_tmp;
+#ifdef __WATCOMC__
+   ostrstream ostr;
+#else
+   ostringstream ostr;
+#endif
+#ifdef _MSC_VER  
+   ostr << value; // need to be fixed !
+#else
+   ostr << setprecision(13) << value;
+#endif
+   value_tmp = ostr.str();
+
+   add_string(section, parameter, value_tmp);
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/config.h
===================================================================
RCS file: Motion/roboop/config.h
diff -N Motion/roboop/config.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/config.h	1 Sep 2004 19:51:04 -0000	1.9
@@ -0,0 +1,173 @@
+/*
+Copyright (C) 2003-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polytml.ca or richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+    -Added dependance on utils.h because we need to get the use_namespace setting
+
+2004/07/13: Ethan Tira-Thompson
+    -Added a select_real and add_real function for type indepence of Real
+    -Added functions to test for sections and parameters existance
+
+2004/07/23: Ethan Tira-Thompson
+    -Fixed potentially uninitialized variables and some other warnings
+
+2004/09/01: Ethan Tira-Thompson
+    -Added optional parameter to constructor so you can automatically read_conf
+    -select_* functions are now const
+-------------------------------------------------------------------------------
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/*!
+  @file config.h
+  @brief Header file for Config class definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_config_rcsid[] = "$Id: config.h,v 1.9 2004/09/01 19:51:04 ejt Exp $";
+
+
+#ifdef _MSC_VER                  // Microsoft
+#pragma warning (disable:4786)  // Disable decorated name truncation warnings 
+#pragma warning (disable:4503)  // Disable decorated name truncation warnings 
+#endif
+#include <iostream>
+#include <string>
+#include <iomanip>
+#include <fstream>
+#ifdef __WATCOMC__
+#include <strstrea.h>
+#else
+#include <sstream>
+#endif
+#include <vector>
+
+#include "utils.h"
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+//! @brief Return when can not open file.
+#define CAN_NOT_OPEN_FILE                     -1
+
+//! @brief Return when can not create a file.
+#define CAN_NOT_CREATE_FILE                   -2
+
+//! @brief Return when a section or parameter does not exist.
+#define SECTION_OR_PARAMETER_DOES_NOT_EXIST   -3
+
+#ifndef __WATCOMC__
+using namespace std;
+#endif
+
+
+//! @brief Basic data element used in Config class.
+typedef struct Data{
+   Data() : section(), parameter(), value() {}
+   string section;
+   string parameter;
+   string value;
+} Data;
+
+//! @brief Configuration data type.
+typedef vector< Data > Conf_data;
+
+//! @brief Handle configuration files.
+class Config {
+public:
+   Config() : conf(), filename() {}
+   Config(const string & filename_,bool doRead=false);
+   Config(const Config & x);
+   Config & operator=(const Config & x);
+   short read_conf();
+   void print();
+
+	 bool section_exists(const string& section) const;
+	 bool parameter_exists(const string& section, const string& parameter) const;
+
+   short select_string(const string section, const string parameter,
+                       string & value) const;
+   short select_bool(const string section, const string parameter,
+                     bool & value) const;
+   short select_short(const string section, const string parameter,
+                      short & value) const;
+   short select_int(const string section, const string parameter,
+                    int & value) const;
+   short select_float(const string section, const string parameter,
+		      float & value) const;
+   short select_double(const string section, const string parameter,
+                       double & value) const;
+   short select_real(const string section, const string parameter,
+                       Real & value) const;
+
+   short write_conf(const string name, const string file_title,
+                    const int space_between_column);
+   void add_string(const string section, const string parameter,
+                   const string value);
+   void add_bool(const string section, const string parameter,
+                 const bool value);
+   void add_int(const string section, const string parameter,
+                const int value);
+   void add_float(const string section, const string parameter,
+                   const float value);
+   void add_double(const string section, const string parameter,
+                   const double value);
+   void add_real(const string section, const string parameter,
+                   const Real value);
+
+private:
+   Conf_data conf;   //!< Data store from/to configuration file.
+   string filename;  //!< Configuration file name.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/control_select.cpp
===================================================================
RCS file: Motion/roboop/control_select.cpp
diff -N Motion/roboop/control_select.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/control_select.cpp	14 Jul 2004 02:46:43 -0000	1.3
@@ -0,0 +1,221 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/13: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+    -Using config::select_real instead of select_double
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file control_select.cpp
+  @brief Controller selection class.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: control_select.cpp,v 1.3 2004/07/14 02:46:43 ejt Exp $";
+
+
+#include "control_select.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+Control_Select::Control_Select()
+//! @brief Constructor.
+{
+  type = NONE;
+  space_type = NONE;
+  dof = 0;
+}
+
+Control_Select::Control_Select(const string & filename)
+/*!
+  @brief Constructor.
+  @param filename: configuration file (path+name).
+*/
+{
+    set_control(filename);
+}
+
+Control_Select::Control_Select(const Control_Select & x)
+//! @brief Copy constructor.
+{
+    type = x.type;
+    space_type = x.space_type;
+    dof = x.dof;
+    pd = x.pd;
+    ctm = x.ctm;
+    rra = x.rra;
+    impedance = x.impedance;
+}
+
+Control_Select & Control_Select::operator=(const Control_Select & x)
+//! @brief Overload = operator.
+{
+    type = x.type;
+    space_type = x.space_type;
+    dof = x.dof;
+    pd = x.pd;
+    ctm = x.ctm;
+    rra = x.rra;
+    impedance = x.impedance;
+
+    return *this;
+}
+
+int Control_Select::get_dof()
+//! @brief Return the degree of freedom.
+{ 
+    return dof; 
+}
+
+void Control_Select::set_control(const string & filename)
+//! @brief Select the proper controller from filename. 
+{
+    Config conf(filename);
+    conf.read_conf();
+
+    conf.select_string(CONTROLLER, "type", ControllerName);
+
+    if (ControllerName == PROPORTIONAL_DERIVATIVE)
+    {
+	type = PD;
+	space_type = JOINT_SPACE;
+    }
+    else if(ControllerName == COMPUTED_TORQUE_METHOD)
+    {
+	type = CTM;
+	space_type = JOINT_SPACE;
+    }
+    else if(ControllerName == RESOLVED_RATE_ACCELERATION)
+    {
+	type = RRA;
+	space_type = CARTESIAN_SPACE;
+    }
+    else if(ControllerName == IMPEDANCE)
+    {
+	type = IMP;
+	space_type = CARTESIAN_SPACE;
+    }
+    else 
+    {
+	ControllerName = "";
+	type = 0;
+	space_type = 0;
+    }
+    
+    conf.select_int(CONTROLLER, "dof", dof);
+
+    switch (type) {
+	case PD:
+	{	    
+	    pd = Proportional_Derivative(dof);
+	    DiagonalMatrix Kp(dof), Kd(dof);
+	    for(int i = 1; i <= dof; i++)
+	    {
+#ifdef __WATCOMC__
+		ostrstream Kp_ostr, Kd_ostr;
+		Kp_ostr << "Kp_" << i;
+		string temp = Kp_ostr.str();
+		temp[Kp_ostr.pcount()] = 0;
+		conf.select_real("GAINS", temp.c_str(), Kp(i));
+		Kd_ostr << "Kd_" << i;
+		temp = Kd_ostr.str();
+		temp[Kd_ostr.pcount()] = 0;
+		conf.select_real("GAINS", temp.c_str(), Kd(i));
+#else
+		ostringstream Kp_ostr, Kd_ostr;
+		Kp_ostr << "Kp_" << i;
+		conf.select_real("GAINS", Kp_ostr.str(), Kp(i));
+		Kd_ostr << "Kd_" << i;
+		conf.select_real("GAINS", Kd_ostr.str(), Kd(i));
+#endif
+	    }
+	    pd.set_Kp(Kp);
+	    pd.set_Kd(Kd);	    
+	}
+	break;
+	
+	case CTM:
+	{	    
+	    ctm = Computed_torque_method(dof);
+	    DiagonalMatrix Kp(dof), Kd(dof);
+	    for(int i = 1; i <= dof; i++)
+	    {
+#ifdef __WATCOMC__
+		ostrstream Kp_ostr, Kd_ostr;
+		Kp_ostr << "Kp_" << i;
+		string temp = Kp_ostr.str();
+		temp[Kp_ostr.pcount()] = 0;
+		conf.select_real("GAINS", temp.c_str(), Kp(i));
+		Kd_ostr << "Kd_" << i;
+		temp = Kd_ostr.str();
+		temp[Kd_ostr.pcount()] = 0;
+		conf.select_real("GAINS", temp.c_str(), Kd(i));
+#else
+		ostringstream Kp_ostr, Kd_ostr;
+		Kp_ostr << "Kp_" << i;
+		conf.select_real("GAINS", Kp_ostr.str(), Kp(i));
+		Kd_ostr << "Kd_" << i;
+		conf.select_real("GAINS", Kd_ostr.str(), Kd(i));
+#endif
+	    }
+	    ctm.set_Kp(Kp);
+	    ctm.set_Kd(Kd);
+	}
+	break;
+	    
+	case RRA:
+	{
+	    rra = Resolved_acc(dof);
+	    Real Kvp, Kpp, Kvo, Kpo;
+	    conf.select_real("GAINS", "Kvp", Kvp);
+	    conf.select_real("GAINS", "Kpp", Kpp);
+	    conf.select_real("GAINS", "Kvo", Kvo);
+	    conf.select_real("GAINS", "Kpo", Kpo);
+	    rra.set_Kvp( Kvp );
+	    rra.set_Kpp( Kpp );
+	    rra.set_Kvo( Kvo );
+	    rra.set_Kpo( Kpo );
+	}
+	break;
+
+	case IMP:
+	{
+	}
+	break;
+	
+	default:
+	    break;
+    }
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Motion/roboop/control_select.h
===================================================================
RCS file: Motion/roboop/control_select.h
diff -N Motion/roboop/control_select.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/control_select.h	14 Jul 2004 02:46:43 -0000	1.3
@@ -0,0 +1,139 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/13: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+
+#ifndef CONTROL_SELECT_H
+#define CONTROL_SELECT_H
+
+/*!
+  @file control_select.h
+  @brief Header file for Control_Select class definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_Control_Select_rcsid[] = "$Id: control_select.h,v 1.3 2004/07/14 02:46:43 ejt Exp $";
+
+
+#include <string>
+#include <vector>
+#include "robot.h"
+#include "config.h"
+#include "controller.h"
+#include "trajectory.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#define NONE   0
+#define PD     1
+#define CTM    2
+#define RRA    3
+#define IMP    4
+
+#define CONTROLLER  "CONTROLLER"
+
+#define PROPORTIONAL_DERIVATIVE    "PROPORTIONAL_DERIVATIVE"
+#define COMPUTED_TORQUE_METHOD     "COMPUTED_TORQUE_METHOD"
+#define RESOLVED_RATE_ACCELERATION "RESOLVED_RATE_ACCELERATION"
+#define IMPEDANCE                  "IMPEDANCE"
+
+/*!
+  @class Control_Select
+  @brief Select controller class.
+
+  This class contains an instance of each controller class. The active controller
+  will be selected when reading a controller file. "type" value correspond to the
+  active controller, ex:
+  \li <tt> type = NONE </tt>: no controller selected
+  \li <tt> type = PD </tt>: Proportional Derivative 
+  \li <tt> type = CTM </tt>: Computer Torque Method
+  \li <tt> type = RRA </tt>: Resolved Rate Acceleration
+  \li <tt> type = IMP </tt>: Impedance
+
+  Bellow is an exemple of RRA configuration file (more info on configuration
+  file in config.h/cpp):
+
+\verbatim
+  [CONTROLLER]
+
+  type:   RESOLVED_RATE_ACCELERATION
+  dof:    6
+
+  [GAINS]
+
+  Kvp:         500.0
+  Kpp:        5000.0
+  Kvo:         500.0
+  Kpo:        5000.0
+\endverbatim
+*/
+class Control_Select
+{
+public:
+    Control_Select();
+    Control_Select(const string & filename);
+    Control_Select(const Control_Select & x);
+    Control_Select & operator=(const Control_Select & x);
+    int get_dof();
+    void set_control(const string & filename);
+    Proportional_Derivative pd;
+    Computed_torque_method ctm;
+    Resolved_acc rra;
+    Impedance impedance;
+
+    short type,            //!< Type of controller: PD, CTM,...
+	  space_type;      //!< JOINT_SPACE or CARTESIAN_SPACE.
+    string ControllerName; //!< Controller name.
+private:
+    int dof;               //!< Degree of freedom.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/controller.cpp
===================================================================
RCS file: Motion/roboop/controller.cpp
diff -N Motion/roboop/controller.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/controller.cpp	14 Jul 2004 02:32:11 -0000	1.2
@@ -0,0 +1,809 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+*/
+
+/*!
+  @file controller.cpp
+  @brief Differents controllers class.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: controller.cpp,v 1.2 2004/07/14 02:32:11 ejt Exp $";
+
+
+#include "controller.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+Impedance::Impedance()
+//! @brief Constructor.
+{
+   pc = ColumnVector(3); pc = 0;
+   pcp = pc;
+   pcpp = pc;
+   pcpp_prev = pc;
+   qc = Quaternion();
+   qcp = qc;
+   qcp_prev = qc;
+   quat = qc;
+   wc = pc;
+   wcp = pc;
+}
+
+Impedance::Impedance(const Robot_basic & robot, const DiagonalMatrix & Mp_,
+                     const DiagonalMatrix & Dp_, const DiagonalMatrix & Kp_,
+                     const DiagonalMatrix & Mo_, const DiagonalMatrix & Do_, 
+		     const DiagonalMatrix & Ko_)
+//! @brief Constructor.
+{
+   set_Mp(Mp_);
+   set_Dp(Dp_);
+   set_Kp(Kp_);
+   set_Mo(Mo_);
+   set_Do(Do_);
+   set_Ko(Ko_);
+
+   pc = ColumnVector(3); pc = 0;
+   pcp = pc;
+   pcp_prev = pc;
+   pcpp = pc;
+   pcpp_prev = pc;
+   qc = Quaternion();
+   qcp = qc;
+   qcp_prev = qc;
+   quat = qc;
+   wc = pc;
+   wcp = pc;
+   wcp_prev = pc;
+
+   Matrix Rot;
+   robot.kine(Rot, pc);
+   qc = Quaternion(Rot);
+}
+
+Impedance::Impedance(const Impedance & x)
+//! @brief Copy constructor.
+{
+   Mp = x.Mp;
+   Dp = x.Dp;
+   Kp = x.Kp;
+   Mo = x.Mo;
+   Do = x.Do;
+   Ko = x.Ko;
+   Ko_prime = x.Ko_prime;
+   pc = x.pc;
+   pcp = x.pcp;
+   pcp_prev = x.pcp_prev;
+   pcpp = x.pcpp;
+   pcpp_prev = x.pcpp_prev;
+   qc = x.qc;
+   qcp = x.qcp;
+   qcp_prev = x.qcp_prev;
+   quat = x.quat;
+   wc = x.wc;
+   wcp = x.wcp;
+   wcp_prev = x.wcp_prev;
+}
+
+Impedance & Impedance::operator=(const Impedance & x)
+//! @brief Overload = operator.
+{
+   Mp = x.Mp;
+   Dp = x.Dp;
+   Kp = x.Kp;
+   Mo = x.Mo;
+   Do = x.Do;
+   Ko = x.Ko;
+   Ko_prime = x.Ko_prime;
+   pc = x.pc;
+   pcp = x.pcp;
+   pcp_prev = x.pcp_prev;
+   pcpp = x.pcpp;
+   pcpp_prev = x.pcpp_prev;
+   qc = x.qc;
+   qcp = x.qcp;
+   qcp_prev = x.qcp_prev;
+   quat = x.quat;
+   wc = x.wc;
+   wcp = x.wcp;
+   wcp_prev = x.wcp_prev;
+
+   return *this;
+}
+
+short Impedance::set_Mp(const DiagonalMatrix & Mp_)
+/*!
+  @brief Assign the translational impedance inertia matrix \f$M_p\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if(Mp_.Nrows() != 3)
+   {
+      Mp = DiagonalMatrix(3); Mp = 1;
+      cerr << "Impedance::set_Mp: wrong size for input matrix Mp" << endl;
+      return WRONG_SIZE;
+   }
+
+   Mp = Mp_;
+   return 0;
+}
+
+short Impedance::set_Mp(const Real Mp_i, const short i)
+/*!
+  @brief Assign the translational impedance inertia term \f$M_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Mp: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Mp(i) = Mp_i;
+   return 0;
+}
+
+short Impedance::set_Dp(const DiagonalMatrix & Dp_)
+/*!
+  @brief Assign the translational impedance damping matrix \f$D_p\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if(Dp_.Nrows() != 3)
+   {
+      Dp = DiagonalMatrix(3); Dp = 1;
+      cerr << "Impedance::set_Dp: input matrix Dp of wrong size" << endl;
+      return WRONG_SIZE;
+   }
+
+   Dp = Dp_;
+   return 0;
+}
+
+short Impedance::set_Dp(const Real Dp_i, const short i)
+/*!
+  @brief Assign the translational impedance damping term \f$D_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Dp: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Dp(i) = Dp_i;
+   return 0;
+}
+
+short Impedance::set_Kp(const DiagonalMatrix & Kp_)
+/*!
+  @brief Assign the translational impedance stifness matrix \f$K_p\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if(Kp_.Nrows() != 3)
+   {
+      Kp = DiagonalMatrix(3); Kp = 1;
+      cerr << "Impedance::set_Kp: wrong size for input matrix Kp" << endl;
+      return WRONG_SIZE;
+   }
+
+   Kp = Kp_;
+   return 0;
+}
+
+short Impedance::set_Kp(const Real Kp_i, const short i)
+/*!
+  @brief Assign the translational impedance stifness term \f$K_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Mp: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Kp(i) = Kp_i;
+   return 0;
+}
+
+short Impedance::set_Mo(const DiagonalMatrix & Mo_)
+/*!
+  @brief Assign the rotational impedance inertia matrix \f$M_o\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if(Mo_.Nrows() != 3)
+   {
+      Mo = DiagonalMatrix(3); Mo = 1;
+      cerr << "Impedance::set_Mo: wrong size  input matrix Mo" << endl;
+      return WRONG_SIZE;
+   }
+
+   Mo = Mo_;
+   return 0;
+}
+
+short Impedance::set_Mo(const Real Mo_i, const short i)
+/*!
+  @brief Assign the rotational impedance inertia term \f$M_o(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Mo: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Mo(i) = Mo_i;
+   return 0;
+}
+
+short Impedance::set_Do(const DiagonalMatrix & Do_)
+/*!
+  @brief Assign the rotational impedance damping matrix \f$D_o\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( Do_.Nrows() != 3)
+   {
+      Do = DiagonalMatrix(3); Do = 1;
+      cerr << "Impedance::set_Do: wrong size  input matrix Do" << endl;
+      return WRONG_SIZE;
+   }
+
+   Do = Do_;
+   return 0;
+}
+
+short Impedance::set_Do(const Real Do_i, const short i)
+/*!
+  @brief Assign the rotational impedance damping term \f$D_o(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Do: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Do(i) = Do_i;
+   return 0;
+}
+
+short Impedance::set_Ko(const DiagonalMatrix & Ko_)
+/*!
+  @brief Assign the rotational impedance stifness matrix \f$K_o\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if(Ko_.Nrows() != 3)
+   {
+      Ko = DiagonalMatrix(3); Ko = 1;
+      cerr << "Impedance::set_Ko: wrong size for  input matrix Ko" << endl;
+      return WRONG_SIZE;
+   }
+
+   Ko = Ko_;
+   return 0;
+}
+
+short Impedance::set_Ko(const Real Ko_i, const short i)
+/*!
+  @brief Assign the rotational impedance stifness term \f$K_o(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$3\times 3\f$.
+*/
+{
+   if( (i < 0) || (i > 3) )
+   {
+      cerr << "Impedance::set_Ko: index i out of bound" << endl;
+      return WRONG_SIZE;
+   }
+
+   Ko(i) = Ko_i;
+   return 0;
+}
+
+short Impedance::control(const ColumnVector & pdpp, const ColumnVector & pdp,
+                         const ColumnVector & pd, const ColumnVector & wdp,
+                         const ColumnVector & wd, const Quaternion & qd,
+                         const ColumnVector & f, const ColumnVector & n,
+                         const Real dt)
+/*!
+  @brief Generation of a compliance trajectory
+  @param pdpp: desired end effector acceleration.
+  @param pdp: desired end effector velocity.
+  @param pd: desired end effector position.
+  @param wdp: desired end effector angular acceleration.
+  @param wd: desired end effector angular velocity.
+  @param qd: desired quaternion.
+  @param f: end effector contact force.
+  @param n: end effector contact moment.
+  @param dt: time frame.
+
+  @return short: 0 or WRONG_SIZE if one of the vector input is not \f$3\times 1\f$.
+
+  The translational and rotational impedance equations are integrated, with input 
+  \f$f\f$ and \f$n\f$ to computed \f$\ddot{p}_c\f$ and \f$\dot{\omega}_c\f$, 
+  \f$\dot{p}_c\f$ and \f$\omega_c\f$, and then \f$p_c\f$ and \f$q_c\f$. The compliant
+  quaternion \f$q_c\f$ is obtained with the quaternion propagation equations (see 
+  Quaternion class).
+
+  The quaternion -q represents exactly the same rotation as the quaternion q. The 
+  temporay quaternion, quat, is quatd plus a sign correction. It is customary to 
+  choose the sign G on q1 so that q0.Gq1 >=0 (the angle between q0 ang Gq1 is acute). 
+  This choice avoids extra spinning caused by the interpolated rotations.
+*/
+{
+   if(pdpp.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector pdpp" << endl;
+      return WRONG_SIZE;
+   }
+   if(pdp.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector pdp" << endl;
+      return WRONG_SIZE;
+   }
+   if(pd.Nrows() != 3)
+   {
+      cerr << "Impedance::control: wrong size for input vector pd" << endl;
+      return WRONG_SIZE;
+   }
+   if(wdp.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector wdp" << endl;
+      return WRONG_SIZE;
+   }
+   if(wd.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector wd" << endl;
+      return WRONG_SIZE;
+   }
+   if(f.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector f" << endl;
+      return WRONG_SIZE;
+   }
+   if(n.Nrows() !=3)
+   {
+      cerr << "Impedance::control: wrong size for input vector f" << endl;
+      return WRONG_SIZE;
+   }
+
+   static bool first=true;
+   if(first)
+   {
+      qc = qd;
+      qcp = qc.dot(wc, BASE_FRAME);
+      qcp_prev = qcp;
+      wc = wd;
+      wcp = wdp;
+      first = false;
+   }
+   if(qc.dot_prod(qd) < 0)
+      quat = qd*(-1);
+   else
+      quat = qd;
+
+   qcd = quat * qc.i();
+
+   // Solving pcpp, pcp, pc with the translational impedance
+   pcd = pc - pd;
+   pcdp = pcp - pdp;
+   //  pcpp = pdpp + Mp.i()*(f - Dp*pcdp - Kp*pcd - 2*qcd.s()*Km.t()*qcd.v()); // (21)
+   pcpp = pdpp + Mp.i()*(f - Dp*pcdp - Kp*pcd);
+   pcp = pcp_prev + Integ_Trap(pcpp, pcpp_prev, dt);
+   pc = pc + Integ_Trap(pcp, pcp_prev, dt);
+
+   // Solving wcp, wc, qc with the rotational impedance
+   wcd = wc - wd;
+   Ko_prime = 2*qcd.E(BASE_FRAME)*Ko;                                   //(23)
+   //  Km_prime = (qcd.s()*qcd.E(BASE_FRAME) - qcd.v()*qcd.v().t())*Km;   // (24)
+   //  wcp = wdp + Mo.i()*(n - Do*wcd - Ko_prime*qcd.v() - Km_prime*pcd); // (22)
+   wcp = wdp + Mo.i()*(n - Do*wcd - Ko_prime*qcd.v()); // (22)
+   wc = wc + Integ_Trap(wcp, wcp_prev, dt);
+   qcp = qc.dot(wc, BASE_FRAME);
+   Integ_quat(qcp, qcp_prev, qc, dt);
+
+   return 0;
+}
+
+// ------------------------------------------------------------------------------------------------------
+//  Position control based on resolved acceleration.
+// ------------------------------------------------------------------------------------------------------
+
+Resolved_acc::Resolved_acc(const short dof)
+//! @brief Constructor.
+{
+   Kvp = Kpp = Kvo = Kpo = 0;
+   zero3 = ColumnVector(3); zero3 = 0;
+   p = zero3;
+   pp = zero3;
+
+   if(dof>0)
+   {
+       qp = ColumnVector(dof); qp = 0;
+       qpp = qp;
+   }
+
+   quat_v_error = zero3;
+   a = ColumnVector(6); a = 0;
+   quat = Quaternion();
+}
+
+Resolved_acc::Resolved_acc(const Robot_basic & robot,
+                           const Real Kvp_,
+                           const Real Kpp_,
+                           const Real Kvo_,
+                           const Real Kpo_)
+//! @brief Constructor.
+{
+   set_Kvp(Kvp_);
+   set_Kpp(Kpp_);
+   set_Kvo(Kvo_);
+   set_Kpo(Kpo_);
+   zero3 = ColumnVector(3); zero3 = 0;
+   qp = ColumnVector(robot.get_dof()); qp = 0;
+   qpp = qp;
+   a = ColumnVector(6); a = 0;
+   p = zero3;
+   pp = zero3;
+   quat_v_error = zero3;
+   quat = Quaternion();
+}
+
+Resolved_acc::Resolved_acc(const Resolved_acc & x)
+//! @brief Copy constructor.
+{
+   Kvp = x.Kvp;
+   Kpp = x.Kpp;
+   Kvo = x.Kvo;
+   Kpo = x.Kpo;
+   zero3 = x.zero3;
+   qp = x.qp;
+   qpp = x.qpp;
+   a = x.a;
+   p = x.p;
+   pp = x.pp;
+   quat_v_error = x.quat_v_error;
+   quat = x.quat;
+}
+
+Resolved_acc & Resolved_acc::operator=(const Resolved_acc & x)
+//! @brief Overload = operator.
+{
+   Kvp = x.Kvp;
+   Kpp = x.Kpp;
+   Kvo = x.Kvo;
+   Kpo = x.Kpo;
+   zero3 = x.zero3;
+   qp = x.qp;
+   qpp = x.qpp;
+   a = x.a;
+   p = x.p;
+   pp = x.pp;
+   quat_v_error = x.quat_v_error;
+   quat = x.quat;
+
+   return *this;
+}
+
+void Resolved_acc::set_Kvp(const Real Kvp_)
+//! @brief Assign the gain \f$k_{vp}\f$.
+{
+   Kvp = Kvp_;
+}
+
+void Resolved_acc::set_Kpp(const Real Kpp_)
+//! @brief Assign the gain \f$k_{pp}\f$.
+{
+   Kpp = Kpp_;
+}
+
+void Resolved_acc::set_Kvo(const Real Kvo_)
+//! @brief Assign the gain \f$k_{vo}\f$.
+{
+   Kvo = Kvo_;
+}
+
+void Resolved_acc::set_Kpo(const Real Kpo_)
+//! @brief Assign the gain \f$k_{po}\f$.
+{
+   Kpo = Kpo_;
+}
+
+ReturnMatrix Resolved_acc::torque_cmd(Robot_basic & robot, const ColumnVector & pdpp,
+                                      const ColumnVector & pdp, const ColumnVector & pd,
+                                      const ColumnVector & wdp, const ColumnVector & wd,
+                                      const Quaternion & quatd, const short link_pc,
+                                      const Real dt)
+/*!
+  @brief Output torque.
+
+  For more robustess the damped least squares inverse Jacobian is used instead of
+  the inverse Jacobian.
+
+  The quaternion -q represents exactly the same rotation as the quaternion q. The 
+  temporay quaternion, quat, is quatd plus a sign correction. It is customary to 
+  choose the sign G on q1 so that q0.Gq1 >=0 (the angle between q0 ang Gq1 is acute). 
+  This choice avoids extra spinning caused by the interpolated rotations.
+*/
+{
+   robot.kine_pd(Rot, p, pp, link_pc);
+
+   Quaternion quate(Rot); // end effector orientation
+   if(quate.dot_prod(quatd) < 0)
+      quat = quatd*(-1);
+   else
+      quat = quatd;
+
+   quat_v_error = quate.s()*quat.v() - quat.s()*quate.v() +
+                  x_prod_matrix(quate.v())*quat.v();
+
+   a.SubMatrix(1,3,1,1) = pdpp + Kvp*(pdp-pp) + Kpp*(pd-p);
+   a.SubMatrix(4,6,1,1) = wdp + Kvo*(wd-Rot*robot.w[robot.get_dof()]) +
+                          Kpo*quat_v_error;
+   qp = robot.get_qp();
+   //                          (eps, lamda_max)
+   qpp = robot.jacobian_DLS_inv(0.015, 0.2)*(a - robot.jacobian_dot()*qp);
+   return robot.torque(robot.get_q(),qp, qpp, zero3, zero3);
+}
+
+
+// ------------------------------------------------------------------------------
+//  Position control based on Computed Torque Method
+// ------------------------------------------------------------------------------
+
+Computed_torque_method::Computed_torque_method(const short dof_)
+//! @brief Constructor.
+{
+    dof = dof_;
+    qpp = ColumnVector(dof); qpp = 0;
+    q = qpp;
+    qp = qpp;
+    zero3 = ColumnVector(3); zero3 = 0;
+}
+
+Computed_torque_method::Computed_torque_method(const Robot_basic & robot,
+					       const DiagonalMatrix & Kp,
+					       const DiagonalMatrix & Kd)
+//! @brief Constructor.
+{
+   dof = robot.get_dof();
+   set_Kd(Kd);
+   set_Kp(Kp);
+   qpp = ColumnVector(dof); qpp = 0;
+   q = qpp;
+   qp = qpp;
+   zero3 = ColumnVector(3); zero3 = 0;
+}
+
+Computed_torque_method::Computed_torque_method(const Computed_torque_method & x)
+//! @brief Copy constructor.
+{
+   dof = x.dof;
+   Kd = x.Kd;
+   Kp = x.Kp;
+   qpp = x.qpp;
+   q = x.q;
+   qp = x.qp;
+   zero3 = x.zero3;
+}
+
+Computed_torque_method & Computed_torque_method::operator=(const Computed_torque_method & x)
+//! @brief Overload = operator.
+{
+   dof = x.dof;
+   Kd = x.Kd;
+   Kp = x.Kp;
+   qpp = x.qpp;
+   q = x.q;
+   qp = x.qp;
+   zero3 = x.zero3;
+
+   return *this;
+}
+
+ReturnMatrix Computed_torque_method::torque_cmd(Robot_basic & robot, const ColumnVector & qd,
+						const ColumnVector & qpd)
+//! @brief Output torque.
+{
+   if(qd.Nrows() != dof)
+   {
+      ColumnVector tau(dof); tau = 0;
+      cerr << "Computed_torque_methode::torque_cmd: wrong size for input vector qd" << endl;
+      tau.Release();
+      return tau;
+   }
+   if(qpd.Nrows() != dof)
+   {
+      ColumnVector tau(dof); tau = 0;
+      cerr << "Computed_torque_methode::torque_cmd: wrong size for input vector qpd" << endl;
+      tau.Release();
+      return tau;
+   }
+
+   q = robot.get_q();
+   qp = robot.get_qp();
+   qpp = Kp*(qd-q) + Kd*(qpd-qp);
+   return robot.torque(q, qp, qpp, zero3, zero3);
+}
+
+short Computed_torque_method::set_Kd(const DiagonalMatrix & Kd_)
+/*!
+  @brief Assign the velocity error gain matrix \f$K_d(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$dof \times dof\f$.
+*/
+{
+   if(Kd_.Nrows() != dof)
+   {
+      Kd = DiagonalMatrix(dof); Kd = 0;
+      cerr << "Computed_torque_method::set_kd: wrong size for input matrix Kd." << endl;
+      return WRONG_SIZE;
+   }
+
+   Kd = Kd_;
+   return 0;
+}
+
+short Computed_torque_method::set_Kp(const DiagonalMatrix & Kp_)
+/*!
+  @brief Assign the position error gain matrix \f$K_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$dof \times dof\f$.
+*/
+{
+   if(Kp_.Nrows() != dof)
+   {
+      Kp = DiagonalMatrix(dof); Kp = 0;
+      cerr << "Computed_torque_method::set_kp: wrong size for input matrix Kp." << endl;
+      return WRONG_SIZE;
+   }
+
+   Kp = Kp_;
+   return 0;
+}
+
+// ------------------------------------------------------------------------------
+//  Position control based on Proportional_Derivative (PD)
+// ------------------------------------------------------------------------------
+
+Proportional_Derivative::Proportional_Derivative(const short dof_)
+//! @brief Constructor.
+{
+  dof = dof_;
+  q = ColumnVector(dof); q = 0;
+  qp = q;
+  zero3 = ColumnVector(3); zero3 = 0;
+}
+
+Proportional_Derivative::Proportional_Derivative(const Robot_basic & robot, 
+						 const DiagonalMatrix & Kp, 
+						 const DiagonalMatrix & Kd)
+//! @brief Constructor.
+{
+   dof = robot.get_dof();
+   set_Kp(Kp);
+   set_Kd(Kd);
+   q = ColumnVector(dof); q = 0;
+   qp = q;
+   tau = ColumnVector(dof); tau = 0;
+   zero3 = ColumnVector(3); zero3 = 0;
+}
+
+Proportional_Derivative::Proportional_Derivative(const Proportional_Derivative & x)
+//! @brief Copy constructor.
+{
+   dof = x.dof;
+   Kp = x.Kp;
+   Kd = x.Kd;
+   q = x.q;
+   qp = x.qp;
+   tau = x.tau;
+   zero3 = x.zero3;
+}
+
+Proportional_Derivative & Proportional_Derivative::operator=(const Proportional_Derivative & x)
+//! @brief Overload = operator.
+{
+   dof = x.dof;
+   Kp = x.Kp;
+   Kd = x.Kd;
+   q = x.q;
+   qp = x.qp;
+   tau = x.tau;
+   zero3 = x.zero3;
+
+   return *this;
+}
+
+ReturnMatrix Proportional_Derivative::torque_cmd(Robot_basic & robot, 
+						 const ColumnVector & qd,
+						 const ColumnVector & qpd)
+//! @brief Output torque.
+{
+   if(qd.Nrows() != dof)
+   {
+      tau = 0;
+      cerr << "Proportional_Derivative::torque_cmd: wrong size for input vector qd" << endl;
+      return tau;
+   }
+   if(qpd.Nrows() != dof)
+   {
+      tau = 0;
+      cerr << "Proportional_Derivative::torque_cmd: wrong size for input vector qpd" << endl;
+      return tau;
+   }
+
+   q = robot.get_q();
+   qp = robot.get_qp();
+   tau = Kp*(qd-q) + Kd*(qpd-qp);
+
+   return tau;
+}
+
+short Proportional_Derivative::set_Kd(const DiagonalMatrix & Kd_)
+/*!
+  @brief Assign the velocity error gain matrix \f$K_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$dof \times dof\f$.
+*/
+{
+   if(Kd_.Nrows() != dof)
+   {
+      Kd = DiagonalMatrix(dof); Kd = 0;
+      cerr << "Proportional_Derivative::set_kd: wrong size for input matrix Kd." << endl;
+      return WRONG_SIZE;
+   }
+
+   Kd = Kd_;
+   return 0;
+}
+
+short Proportional_Derivative::set_Kp(const DiagonalMatrix & Kp_)
+/*!
+  @brief Assign the position error gain matrix \f$K_p(i,i)\f$.
+  @return short: 0 or WRONG_SIZE if the matrix is not \f$dof \times dof\f$.
+*/
+{
+   if(Kp_.Nrows() != dof)
+   {
+      Kp = DiagonalMatrix(dof); Kp = 0;
+      cerr << "Computed_torque_method::set_kp: wrong size for input matrix Kp." << endl;
+      return WRONG_SIZE;
+   }
+
+   Kp = Kp_;
+   return 0;
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/controller.h
===================================================================
RCS file: Motion/roboop/controller.h
diff -N Motion/roboop/controller.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/controller.h	14 Jul 2004 02:46:43 -0000	1.3
@@ -0,0 +1,286 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/13: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+#ifndef CONTROLLER_H
+#define CONTROLLER_H
+
+/*!
+  @file controller.h
+  @brief Header file for controller class definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_controller_rcsid[] = "$Id: controller.h,v 1.3 2004/07/14 02:46:43 ejt Exp $";
+
+
+#include "robot.h"
+#include "quaternion.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+//! @brief Return value when input vectors or matrix don't have the right size.
+#define WRONG_SIZE -1
+
+/*!
+  @class Impedance
+  @brief Impedance controller class.
+
+  The implemantation of the impedance controller is made of two section:
+  the first one is the generation of a compliance trajectory and the second one 
+  used a position controller to ensure the end effector follow the compliance
+  trajectory (We recommended to used the resolve acceleration controller 
+  scheme, implemented in the class Resolved_acc).
+
+  This class generate a compliance path given by the translational
+  and the rotational impedance.
+  \f[
+    M_p\ddot{\tilde{p}} + D_p\dot{\tilde{p}} + K_p\tilde{p} = f
+  \f]
+  \f[
+    M_o\dot{\tilde{\omega}} + D_o\tilde{\omega} + K_o'\tilde{v} = n
+  \f]
+  where \f$\tilde{x} = x_c - x_d\f$ and \f$ v\f$ is the vector par of the 
+  quaternion representing the orientation error between the compliant and desired
+  frame. The orientation error can also be express by rotation matrix, 
+  \f$ \tilde{R} = R_d^TR_c\f$. The quaternion mathematics are implemented in 
+  the Quaternion class. The index \f$_c\f$ and \f$_d\f$ denote 
+  the compliance and the desired respectively. 
+
+  The impedance parameters \f$M_p\f$, \f$D_p\f$, \f$K_p\f$, \f$M_o\f$, \f$D_o\f$ 
+  and \f$K_o\f$ are \f$3\times 3\f$ diagonal positive definite matrix
+*/
+class Impedance{
+public:
+   Impedance();
+   Impedance(const Robot_basic & robot, const DiagonalMatrix & Mp_,
+             const DiagonalMatrix & Dp_, const DiagonalMatrix & Kp_,
+             const DiagonalMatrix & Mo_, const DiagonalMatrix & Do_, 
+	     const DiagonalMatrix & Ko_);
+   Impedance(const Impedance & x);
+   Impedance & operator=(const Impedance & x);
+   short set_Mp(const DiagonalMatrix & Mp_);
+   short set_Mp(const Real MP_i, const short i);
+   short set_Dp(const DiagonalMatrix & Dp_);
+   short set_Dp(const Real Dp_i, const short i);
+   short set_Kp(const DiagonalMatrix & Kp_);
+   short set_Kp(const Real Kp_i, const short i);
+   short set_Mo(const DiagonalMatrix & Mo_);
+   short set_Mo(const Real Mo_i, const short i);
+   short set_Do(const DiagonalMatrix & Do_);
+   short set_Do(const Real Do_i, const short i);
+   short set_Ko(const DiagonalMatrix & Ko_);
+   short set_Ko(const Real Ko_i, const short i);
+   short control(const ColumnVector & pdpp, const ColumnVector & pdp,
+                 const ColumnVector & pd, const ColumnVector & wdp,
+                 const ColumnVector & wd, const Quaternion & qd,
+                 const ColumnVector & f, const ColumnVector & n,
+                 const Real dt);
+
+   Quaternion qc,          //!< Compliant frame quaternion.
+              qcp,         //!< Compliant frame quaternion derivative.
+              qcp_prev,    //!< Previous value of qcp.
+              qcd,         //!< Orientation error (betweem compliant and desired frame) quaternion.
+             quat;         //!< Temporary quaternion.
+   ColumnVector pc,        //!< Compliant position.
+                pcp,       //!< Compliant velocity.
+                pcpp,      //!< Compliant acceleration.
+                pcp_prev,  //!< Previous value of pcp.
+                pcpp_prev, //!< Previous value of pcpp.
+                pcd,       //!< Difference between pc and desired position.
+                pcdp,      //!< Difference between pcp and desired velocity.
+                wc,        //!< Compliant angular velocity.
+                wcp,       //!< Compliant angular acceleration.
+                wcp_prev,  //!< Previous value of wcp.
+                wcd;       //!< Difference between wc and desired angular velocity.
+private:
+   DiagonalMatrix Mp,   //!< Translational impedance inertia matrix.
+                  Dp,   //!< Translational impedance damping matrix.
+                  Kp,   //!< Translational impedance stifness matrix.
+                  Mo,   //!< Rotational impedance inertia matrix.
+                  Do,   //!< Rotational impedance damping matrix.
+                  Ko;   //!< Rotational impedance stifness matrix.
+   Matrix Ko_prime;     //!< Modified rotational impedance stifness matrix.
+};
+
+/*!
+  @class Resolved_acc
+  @brief Resolved rate acceleration controller class.
+
+  The dynamic model of a robot manipulator can be expressed in
+  joint space as
+  \f[
+    B(q)\ddot{q} + C(q,\dot{q})\dot{q} + D\dot{q} + g(q) = \tau - J^T(q)f
+  \f]
+  According to the concept of inverse dynamics, the driving torques
+  can be chosen as
+  \f[
+    \tau = B(q)J^{-1}(q)\big(a - \dot{J}(q,\dot{q})\dot{q}\big) +
+    C(q,\dot{q})\dot{q} + D\dot{q} + g(q) - J^T(q)f
+  \f]
+  where \f$a\f$ is the a new control input defined by
+  \f[
+    a_p = \ddot{p}_d + k_{vp}\dot{\tilde{p}} + k_{pp}\tilde{p}
+  \f]
+  \f[
+    a_o = \dot{\omega}_d + k_{vo}\dot{\tilde{\omega}} + k_{po}\tilde{v}
+  \f]
+  where \f$\tilde{x} = x_c - x_d\f$ and \f$ v\f$ is the vector par of the 
+  quaternion representing the orientation error between the desired and end 
+  effector frame. \f$k_{vp}\f$, \f$k_{pp}\f$, \f$k_{vo}\f$ and \f$k_{po}\f$ 
+  are positive gains.
+  
+  Up to now this class has been tested only with a 6 dof robot.
+*/
+class Resolved_acc {
+public:
+   Resolved_acc(const short dof = 1);
+   Resolved_acc(const Robot_basic & robot,
+                const Real Kvp, const Real Kpp,
+                const Real Kvo, const Real Kpo);
+   Resolved_acc(const Resolved_acc & x);
+   Resolved_acc & operator=(const Resolved_acc & x);
+   void set_Kvp(const Real Kvp);
+   void set_Kpp(const Real Kpp);
+   void set_Kvo(const Real Kvo);
+   void set_Kpo(const Real Kpo);
+
+   ReturnMatrix torque_cmd(Robot_basic & robot, const ColumnVector & pdpp,
+                           const ColumnVector & pdp, const ColumnVector & pd,
+                           const ColumnVector & wdp, const ColumnVector & wd,
+                           const Quaternion & qd, const short link_pc,
+                           const Real dt);
+private:
+   double Kvp,                //!< Controller gains.
+          Kpp, 
+          Kvo, 
+          Kpo; 
+   Matrix Rot;                //!< Temporay rotation matrix.
+   ColumnVector zero3,        //!< \f$3\times 1\f$ zero vector.
+                qp,           //!< Robot joints velocity.
+                qpp,          //!< Robot joints acceleration.
+                a,            //!< Control input.
+                p,            //!< End effector position.
+                pp,           //!< End effector velocity.
+                quat_v_error; //!< Vector part of error quaternion.
+   Quaternion quat;           //!< Temporary quaternion.
+};
+
+
+/*!
+  @class Computed_torque_method
+  @brief Computer torque method controller class.
+
+  The dynamic model of a robot manipulator can be expressed in
+  joint space as
+  \f[
+    B(q)\ddot{q} + C(q,\dot{q})\dot{q} + D\dot{q} + g(q) = \tau - J^T(q)f
+  \f]
+  The driving torques can be expressed as
+  \f[
+    \tau = B(q)\big(\ddot{q}_d + K_d(\dot{q}_d-\dot{q}) 
+    + K_p(q_d-q)\big) + C(q,\dot{q})\dot{q} + D\dot{q} + g(q) + J^T(q)f
+  \f]
+  where \f$K_p\f$, \f$K_d\f$ are diagonal positive definie matrix.
+*/
+class Computed_torque_method {
+public:
+   Computed_torque_method(const short dof = 1);
+   Computed_torque_method(const Robot_basic & robot,
+                          const DiagonalMatrix & Kp, const DiagonalMatrix & Kd);
+   Computed_torque_method(const Computed_torque_method & x);
+   Computed_torque_method & operator=(const Computed_torque_method & x);
+   ReturnMatrix torque_cmd(Robot_basic & robot, const ColumnVector & qd,
+                           const ColumnVector & qpd);
+   short set_Kd(const DiagonalMatrix & Kd);
+   short set_Kp(const DiagonalMatrix & Kp);
+
+private:
+   int dof;            //!< Degree of freedom.
+   ColumnVector q,     //!< Robot joints positions.
+                qp,    //!< Robot joints velocity.
+                qpp,   //!< Robot joints acceleration.
+                zero3; //!< \f$3\times 1\f$ zero vector.
+   DiagonalMatrix Kp,  //!< Position error gain.
+                  Kd;  //!< Velocity error gain.
+};
+
+
+/*!
+  @class Proportional_Derivative
+  @brief Proportional derivative controller class
+
+  The driving torques can be expressed as
+  \f[
+    \tau = K_p(q_d-q) + K_d(\dot{q}_d-q)
+  \f]
+  where \f$K_p\f$, \f$K_d\f$ are diagonal positive definie matrix.
+*/
+class Proportional_Derivative {
+public:
+   Proportional_Derivative(const short dof = 1);
+   Proportional_Derivative(const Robot_basic & robot, const DiagonalMatrix & Kp, 
+			   const DiagonalMatrix & Kd);
+   Proportional_Derivative(const Proportional_Derivative & x);
+   Proportional_Derivative & operator=(const Proportional_Derivative & x);
+   ReturnMatrix torque_cmd(Robot_basic & robot, const ColumnVector & qd,
+                           const ColumnVector & qpd);
+   short set_Kd(const DiagonalMatrix & Kd);
+   short set_Kp(const DiagonalMatrix & Kp);
+
+private:
+   int dof;            //!< Degree of freedom.
+   ColumnVector q,     //!< Robot joints positions.
+                qp,    //!< Robot joints velocity.
+                qpp,   //!< Robot joints acceleration.
+                tau,   //!< Output torque.
+                zero3; //!< \f$3\times 1\f$ zero vector.
+   DiagonalMatrix Kp,  //!< Position error gain.
+                  Kd;  //!< Velocity error gain.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+ 
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/delta_t.cpp
===================================================================
RCS file: Motion/roboop/delta_t.cpp
diff -N Motion/roboop/delta_t.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/delta_t.cpp	3 Sep 2004 15:56:33 -0000	1.5
@@ -0,0 +1,646 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/29/04: Etienne Lachance
+   -Fix Robot::delta_torque.
+   -Added mRobot/mRobot_min_para::delta_torque.
+
+2004/05/14: Etienne Lachance
+   -Replaced vec_x_prod by CrossProduct.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+   -Added Doxygen comments.
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file delta_t.cpp
+  @brief Delta torque (linearized dynamics).
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: delta_t.cpp,v 1.5 2004/09/03 15:56:33 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+void Robot::delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                         const ColumnVector & qpp, const ColumnVector & dq,
+                         const ColumnVector & dqp, const ColumnVector & dqpp,
+                         ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque dynamics.
+
+  This function computes
+  \f[
+    \delta \tau = D(q) \delta \ddot{q}
+    + S_1(q,\dot{q}) \delta \dot{q} + S_2(q,\dot{q},\ddot{q}) \delta q    
+  \f]
+
+  Murray and Neuman Cite_: Murray86 have developed an efficient recursive 
+  linearized Newton-Euler formulation.   In order to apply the RNE as presented in 
+  let us define the following variables 
+
+  \f[
+    p_{di} = \frac{\partial p_i}{\partial d_i} = 
+    \left [
+      \begin{array}{ccc}
+        0 & \sin \alpha_i & \cos \alpha_i 
+      \end{array}
+    \right ]^T
+  \f]
+  \f[
+    Q = 
+    \left [
+      \begin{array}{ccc}
+        0 & -1 & 0  \\
+	1 & 0 & 0  \\
+	0 & 0 & 0 
+      \end{array}
+  \right ]
+  \f]
+
+  Forward Iterations for \f$i=1, 2, \ldots, n\f$. 
+  Initialize: \f$\delta \omega_0 = \delta \dot{\omega}_0 = \delta \dot{v}_0 = 0\f$.
+  \f[
+    \delta \omega_i = R_i^T \{\delta \omega_{i-1} + \sigma_i [ z_0 \delta \dot{\theta}_i 
+    - Q(\omega_{i-1} + \dot{\theta}_i ) \delta \theta_i ] \} 
+  \f]
+  \f[
+  \delta \dot{\omega}_i = R_i^T  \{ \delta \dot{\omega}_{i-1} + 
+  \sigma_i [z_0 \delta \ddot{\theta}_i + \delta \omega_{i-1} \times (z_0 \dot{\theta}_i )
+  + \omega_{i-1} \times (z_0 \delta \dot{\theta}_i )] 
+  - \sigma_i Q [ \omega_{i-1} + z_0 \ddot{\theta}_i 
+  + \omega_{i-1} \times (z_0 \dot{\theta}_i )] \delta \theta_i \}
+  \f]
+
+  \f[
+   \delta \dot{v}_i = R_i^T  \{ \delta \dot{v}_{i-1} - \sigma_i Q \dot{v}_{i-1} \delta \theta_i
+   + (1 -\sigma_i) [z_0 \delta \ddot{d}_i + 2 \delta \omega_{i-1} \times (z_0 \dot{d}_i ) 
+   + 2 \omega_{i-1} \times (z_0 \delta \dot{d}_i )] \} + \delta \dot{\omega}_i \times p_i 
+   + \delta \omega_i \times ( \omega_i \times p_i) + \omega_i \times ( \delta \omega_i \times p_i)
+   + (1 - \sigma_i) (\dot{\omega}_i \times p_{di} 
+   + \omega_i \times ( \omega_i \times p_{di}) ) \delta d_i
+  \f]
+
+  Backward Iterations for \f$i=n, n-1, \ldots, 1\f$. 
+  Initialize: \f$\delta f_{n+1} = \delta n_{n+1} = 0\f$.
+
+  \f[
+  \delta \dot{v}_{ci} =
+  \delta v_i + \delta \omega_i \times r_i 
+  + \delta \omega_i \times (\omega_i \times r_i) 
+  + \omega_i \times (\delta \omega_i \times r_i) 
+  \f]
+  \f[
+  \delta F_i = m_i \delta \dot{v}_{ci}
+  \f]
+  \f[
+  \delta N_i = I_{ci} \delta \dot{\omega}_i 
+  + \delta \omega_i \times (I_{ci} \omega_i) 
+  + \omega_i \times (I_{ci} \delta \omega_i) 
+  \f]
+  \f[
+  \delta f_i = R_{i+1} [ \delta f_{i+1} ]  
+  + \delta F_{i} + \sigma_{i+1} Q R_{i+1} [ f_{i+1} ] \delta \theta_{i+1}
+  \f]
+  \f[
+  \delta n_i = R_{i+1} [ \delta n_{i+1} ]  
+  + \delta N_{i} + p_{i} \times \delta f_{i} 
+  + r_{i} \times \delta F_{i} + (1 - \sigma_i) (p_{di} \times f_{i}) \delta d_i 
+  + \sigma_{i+1} Q R_{i+1} [ n_{i+1} ] \delta \theta_{i+1}
+  \f]
+  \f[
+  \delta \tau_i = \sigma_i [ \delta n_i^T (R_i^T z_0) 
+  - n_i^T (R_i^T Q z_0) \delta \theta_i] + (1 -\sigma_i) [ \delta f_i^T (R_i^T z_0) ]
+  \f]
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || dq.Nrows() != dof) error("dq has wrong dimension");
+   if(dqp.Ncols() != 1 || dqp.Nrows() != dof) error("dqp has wrong dimension");
+   if(dqpp.Ncols() != 1 || dqpp.Nrows() != dof) error("dqpp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0;  z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = ColumnVector(3);
+      p[i](1) = links[i].get_a();
+      p[i](2) = links[i].get_d() * Rt(2,3);
+      p[i](3) = links[i].get_d() * Rt(3,3);
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*(w[i-1] + z0*qp(i));
+         dw[i] = Rt*(dw[i-1] + z0*dqp(i)
+                     - Q*(w[i-1] + z0*qp(i))*dq(i));
+         wp[i] = Rt*(wp[i-1] + z0*qpp(i)
+                     + CrossProduct(w[i-1],z0*qp(i)));
+         dwp[i] = Rt*(dwp[i-1] + z0*dqpp(i)
+                      + CrossProduct(dw[i-1],z0*qp(i))
+                      + CrossProduct(w[i-1],z0*dqp(i))
+                      - Q*(wp[i-1]+z0*qpp(i)+CrossProduct(w[i-1],z0*qp(i)))
+                      *dq(i));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]))
+                 + Rt*(vp[i-1]);
+         dvp[i] = CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]))
+                  + Rt*(dvp[i-1] - Q*vp[i-1]*dq(i));
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + z0*qpp(i)
+                     + 2.0*CrossProduct(w[i-1],z0*qp(i)))
+                 + CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]));
+         dvp[i] = Rt*(dvp[i-1] + z0*dqpp(i)
+                      + 2.0*(CrossProduct(dw[i-1],z0*qp(i))
+                             + CrossProduct(w[i-1],z0*dqp(i))))
+                  + CrossProduct(dwp[i],p[i])
+                  + CrossProduct(dw[i],CrossProduct(w[i],p[i]))
+                  + CrossProduct(w[i],CrossProduct(dw[i],p[i]))
+                  + (CrossProduct(wp[i],dp[i])
+                     + CrossProduct(w[i],CrossProduct(w[i],dp[i])))
+                  *dq(i);
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = a[i] * links[i].m;
+      dF[i] = da[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i].get_joint_type() != 0)
+            dn[i] += CrossProduct(dp[i],f[i])*dq(i);
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i].get_joint_type() == 0)
+            df[i] += Q*links[i+1].R*f[i+1]*dq(i+1);
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i],df[i])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i].get_joint_type() == 0)
+            dn[i] += Q*links[i+1].R*n[i+1]*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i],f[i])*dq(i);
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = ((z0.t()*links[i].R)*n[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*dn[i]);
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = ((z0.t()*links[i].R)*f[i]);
+         ltorque(i) = temp(1,1);
+         temp = ((z0.t()*links[i].R)*df[i]);
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+
+void mRobot::delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                          const ColumnVector & qpp, const ColumnVector & dq,
+                          const ColumnVector & dqp, const ColumnVector & dqpp,
+                          ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque dynamics.
+
+  This function computes
+  \f[
+    \delta \tau = D(q) \delta \ddot{q}
+    + S_1(q,\dot{q}) \delta \dot{q} + S_2(q,\dot{q},\ddot{q}) \delta q    
+  \f]
+
+  Murray and Neuman Cite_: Murray86 have developed an efficient recursive 
+  linearized Newton-Euler formulation.   In order to apply the RNE as presented in 
+  let us define the following variables 
+
+  \f[
+    p_{di} = \frac{\partial p_i}{\partial d_i} = 
+    \left [
+      \begin{array}{ccc}
+        0 & \sin \alpha_i & \cos \alpha_i 
+      \end{array}
+    \right ]^T
+  \f]
+  \f[
+    Q = 
+    \left [
+      \begin{array}{ccc}
+        0 & -1 & 0  \\
+	1 & 0 & 0  \\
+	0 & 0 & 0 
+      \end{array}
+  \right ]
+  \f]
+
+  Forward Iterations for \f$i=1, 2, \ldots, n\f$. 
+  Initialize: \f$\delta \omega_0 = \delta \dot{\omega}_0 = \delta \dot{v}_0 = 0\f$.
+
+  \f[
+  \delta \omega_i = R_i^T \delta \omega_{i-1} + \sigma_i
+  (z_0 \delta \dot{\theta}_i - QR_i^T \omega_i \delta \theta_i) 
+  \f]
+  \f[
+  \delta \dot{\omega}_i = R_i^T \delta \dot{w}_{i-1} +
+  \sigma_i [R_i^T \delta \omega_{i-1} \times z_0 \dot{\theta}_i
+  + R_i^T \omega_{i-1} \times z_0 \delta \dot{\theta}_i  
+  + z_0 \ddot{\theta}_i - (QR_i^T \dot{\omega}_{i-1} + QR_i^T \omega_{i-1}
+  \times \omega{z}_0 \dot{\theta}_i) \delta \theta_i ] 
+  \f]
+  \f[
+  \delta \dot{v}_i = R_i^T\Big(\delta \dot{\omega}_{i-1} \times p_i + \delta \omega_{i-1}
+  \times(\omega_{i-1} \times p_i) + \omega_{i-1} \times( \delta \omega_{i-1} \times p_i) +
+  \delta \dot{v}_i\Big) + (1-\sigma_i)\Big(2\delta \omega_i \times z_0\dot{d}_i
+  + 2\omega_i \times z_0 \delta \dot{d}_i + z_0 \delta \ddot{d}_i\Big) 
+  - \sigma_i QR_i^T \Big(\dot{\omega}_{i-1} \times p_i + \omega_{i-1} \times(w_{i-1}\times p_i)
+  + \dot{v}_i\Big) \delta \theta_i + (1-\sigma_i) R_i^T \Big(\dot{\omega}_{i-1} \times
+  p_{di} + \omega_{i-1} \times(\omega_{i-1}\times p_{di})\Big) \delta d_i
+  \f]
+  
+  Backward Iterations for \f$i=n, n-1, \ldots, 1\f$. 
+  Initialize: \f$\delta f_{n+1} = \delta n_{n+1} = 0\f$.
+
+  \f[
+  \delta \dot{v}_{ci} = \delta \dot{v}_i + \delta \dot{\omega}_i\times
+  r_i + \delta \omega_i \times(\omega_i \times r_i)
+  + \omega_i \times ( \delta \omega_i \times r_i) 
+  \f]
+  \f[
+  \delta F_i = m_i \delta \dot{v}_{ci}
+  \f]
+  \f[
+  \delta N_i = I_{ci} \delta \dot{\omega}_i + \delta
+  \omega_i \times (I_{ci}\omega_i) + \omega_i \times
+  (I_{ci} \delta \omega_i)
+  \f]
+  \f[
+  \delta f_i = R_{i+1} \delta f_{i+1} +
+  \delta F_i + \sigma_{i+1} R_{i+1} Qf_{i+1} \delta \theta_{i+1}
+  \f]
+  \f[
+  \delta n_i = \delta N_i + R_{i+1} \delta n_{i+1} + r_i\times \delta F_i
+  + p_{i+1} \times R_{i+1} \delta f_{i+1} 
+  + \sigma_{i+1} \Big( R_{i+1} Qn_{i+1}
+  + p_{i+1} \times R_{i+1} Qf_{i+1} \Big) \delta
+  \theta_{i+1} + (1-\sigma_{i+1} ) p_{di+1} p_{di+1} \times R_{i+1}
+  f_{i+1} \delta d_{i+1}
+  \f]
+  \f[
+  \delta \tau_i = \sigma \delta n_i^T z_0 +
+  (1 - \sigma_i) \delta f_i^T z_0
+  \f]
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || dq.Nrows() != dof) error("dq has wrong dimension");
+   if(dqp.Ncols() != 1 || dqp.Nrows() != dof) error("dqp has wrong dimension");
+   if(dqpp.Ncols() != 1 || dqpp.Nrows() != dof) error("dqpp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] + z0*dqp(i)
+                 - Q*Rt*w[i-1]*dq(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i))
+                 + z0*qpp(i);
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i))
+                  + CrossProduct(Rt*w[i-1],z0*dqp(i))
+                  - (Q*Rt*wp[i-1] + CrossProduct(Q*Rt*w[i-1],z0*qp(i)))*dq(i)
+                  + z0*dqpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  - Q*Rt*(CrossProduct(wp[i-1],p[i])
+                          + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])) + vp[i-1])*dq(i);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i) + 2.0*CrossProduct(w[i],z0*qp(i));
+
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]
+                      + (CrossProduct(wp[i-1],dp[i])
+                         + CrossProduct(w[i-1],CrossProduct(w[i-1],dp[i])))*dq(i))
+                  + 2*(CrossProduct(dw[i],z0*qp(i)) + CrossProduct(w[i],z0*dqp(i)))
+                  + z0*dqpp(i);
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+      da[i] = CrossProduct(dwp[i],links[i].r)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].r))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].r))
+              + dvp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      dF[i] = da[i] * links[i].m;
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i]);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = dN[i] + CrossProduct(links[i].r,dF[i]);
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i+1].get_joint_type() == 0)
+            df[i] += links[i+1].R*Q*f[i+1]*dq(i+1);
+
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1])
+                 + CrossProduct(links[i].r,dF[i]) + dN[i];
+         if(links[i+1].get_joint_type() == 0)
+            dn[i] += (links[i+1].R*Q*n[i+1] +
+                      CrossProduct(p[i+1],links[i+1].R*Q*f[i+1]))*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i+1],links[i+1].R*f[i+1])*dq(i+1);
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+void mRobot_min_para::delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                                   const ColumnVector & qpp, const ColumnVector & dq,
+                                   const ColumnVector & dqp, const ColumnVector & dqpp,
+                                   ColumnVector & ltorque, ColumnVector & dtorque)
+/*!
+  @brief Delta torque dynamics.
+  
+  See mRobot::delta_torque for equations.
+*/
+{
+   int i;
+   Matrix Rt, temp;
+   if(q.Ncols() != 1 || q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Ncols() != 1 || qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+   if(dq.Ncols() != 1 || dq.Nrows() != dof) error("dq has wrong dimension");
+   if(dqp.Ncols() != 1 || dqp.Nrows() != dof) error("dqp has wrong dimension");
+   if(dqpp.Ncols() != 1 || dqpp.Nrows() != dof) error("dqpp has wrong dimension");
+   ltorque = ColumnVector(dof);
+   dtorque = ColumnVector(dof);
+   set_q(q);
+
+   vp[0] = gravity;
+   ColumnVector z0(3);
+   z0(1) = 0.0; z0(2) = 0.0; z0(3) = 1.0;
+   Matrix Q(3,3);
+   Q = 0.0;
+   Q(1,2) = -1.0;
+   Q(2,1) = 1.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      p[i] = links[i].p;
+      if(links[i].get_joint_type() != 0)
+      {
+         dp[i] = ColumnVector(3);
+         dp[i](1) = 0.0;
+         dp[i](2) = Rt(2,3);
+         dp[i](3) = Rt(3,3);
+      }
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         dw[i] = Rt*dw[i-1] + z0*dqp(i)
+                 - Q*Rt*w[i-1]*dq(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i))
+                 + z0*qpp(i);
+         dwp[i] = Rt*dwp[i-1] + CrossProduct(Rt*dw[i-1],z0*qp(i))
+                  + CrossProduct(Rt*w[i-1],z0*dqp(i))
+                  - (Q*Rt*wp[i-1] + CrossProduct(Q*Rt*w[i-1],z0*qp(i)))*dq(i)
+                  + z0*dqpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1])
+                  - Q*Rt*(CrossProduct(wp[i-1],p[i])
+                          + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])) + vp[i-1])*dq(i);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         dw[i] = Rt*dw[i-1];
+         wp[i] = Rt*wp[i-1];
+         dwp[i] = Rt*dwp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i)+ 2.0*CrossProduct(w[i],z0*qp(i));
+         dvp[i] = Rt*(CrossProduct(dwp[i-1],p[i])
+                      + CrossProduct(dw[i-1],CrossProduct(w[i-1],p[i]))
+                      + CrossProduct(w[i-1],CrossProduct(dw[i-1],p[i])) + dvp[i-1]
+                      + (CrossProduct(wp[i-1],dp[i])
+                         + CrossProduct(w[i-1],CrossProduct(w[i-1],dp[i])))*dq(i))
+                  + 2*(CrossProduct(dw[i],z0*qp(i)) + CrossProduct(w[i],z0*dqp(i)))
+                  + z0*dqpp(i);
+      }
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc) +
+             CrossProduct(w[i], CrossProduct(w[i], links[i].mc));
+      dF[i] = dvp[i]*links[i].m + CrossProduct(dwp[i],links[i].mc)
+              + CrossProduct(dw[i],CrossProduct(w[i],links[i].mc))
+              + CrossProduct(w[i],CrossProduct(dw[i],links[i].mc));
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i])
+             - CrossProduct(vp[i], links[i].mc);
+      dN[i] = links[i].I*dwp[i] + CrossProduct(dw[i],links[i].I*w[i])
+              + CrossProduct(w[i],links[i].I*dw[i])
+              - CrossProduct(dvp[i],links[i].mc);
+
+      if(i == dof)
+      {
+         f[i] = F[i];
+         df[i] = dF[i];
+         n[i] = N[i];
+         dn[i] = dN[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         df[i] = links[i+1].R*df[i+1] + dF[i];
+         if(links[i+1].get_joint_type() == 0)
+            df[i] += links[i+1].R*Q*f[i+1]*dq(i+1);
+
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + N[i];
+         dn[i] = links[i+1].R*dn[i+1] + CrossProduct(p[i+1],links[i+1].R*df[i+1])
+                 + dN[i];
+         if(links[i+1].get_joint_type() == 0)
+            dn[i] += (links[i+1].R*Q*n[i+1] +
+                      CrossProduct(p[i+1],links[i+1].R*Q*f[i+1]))*dq(i+1);
+         else
+            dn[i] += CrossProduct(dp[i+1],links[i+1].R*f[i+1])*dq(i+1);
+      }
+
+      if(links[i].get_joint_type() == 0)
+      {
+         temp = z0.t()*n[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*dn[i];
+         dtorque(i) = temp(1,1);
+      }
+      else
+      {
+         temp = z0.t()*f[i];
+         ltorque(i) = temp(1,1);
+         temp = z0.t()*df[i];
+         dtorque(i) = temp(1,1);
+      }
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/dynamics.cpp
===================================================================
RCS file: Motion/roboop/dynamics.cpp
diff -N Motion/roboop/dynamics.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/dynamics.cpp	14 Jul 2004 03:22:32 -0000	1.6
@@ -0,0 +1,930 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Member function inertia and acceleration are now part of class Robot_basic.
+   -Added torque member funtions to allowed to had load on last link.
+   -Changed variable "n" and "f" for "n_nv" and "f_nv" in torque_novelocity.
+   -Corrected calculation of wp, vp and n in mRobot::torque and 
+    mRobot::torque_novelocity.
+   -Removed all member functions related to classes RobotMotor and mRobotMotor.
+   -Added motor effect in torque function (see ltorque).
+   -Added function call set_qp() and set_qpp in Robot::torque and mRobot::torque.
+
+2003/04/29: Etienne Lachance
+   -Corrected vp calculation for prismatic case in mRobot/mRobot_min_para::torque, 
+    mRobot_min_para::torque_novelocity.
+   -Added functions Robot_basic::acceleration(const ColumnVector & q,const ColumnVector & qp,
+                                              const ColumnVector & tau)
+2003/11/18: Etienne Lachance
+   -Added member function G() (gravity torque) and C() (Coriolis and centrifugal).
+
+2004/05/14: Etienne Lachance
+   -Replaced vec_x_prod by CrossProduct.
+
+2004/05/21: Etienne Lachance
+   -Added doxygen comments.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/13: Ethan Tira-Thompson
+    -Re-added the namespace closing brace at the bottom
+-------------------------------------------------------------------------------
+*/
+/*!
+  @file dynamics.cpp
+  @brief Manipulator dynamics functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: dynamics.cpp,v 1.6 2004/07/14 03:22:32 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+ReturnMatrix Robot_basic::inertia(const ColumnVector & q)
+//! @brief Inertia of the manipulator.
+{
+   Matrix M(dof,dof);
+   ColumnVector torque(dof);
+   set_q(q);
+   for(int i = 1; i <= dof; i++) {
+      for(int j = 1; j <= dof; j++) {
+         torque(j) = (i == j ? 1.0 : 0.0);
+      }
+      torque = torque_novelocity(torque);
+      M.Column(i) = torque;
+   }
+   M.Release(); return M;
+}
+
+
+ReturnMatrix Robot_basic::acceleration(const ColumnVector & q,
+                                       const ColumnVector & qp,
+                                       const ColumnVector & tau_cmd)
+//! @brief Joints acceleration without contact force.
+{
+   ColumnVector qpp(dof);
+   qpp = 0.0;
+   qpp = inertia(q).i()*(tau_cmd-torque(q,qp,qpp));
+   qpp.Release(); 
+   return qpp;
+}
+
+ReturnMatrix Robot_basic::acceleration(const ColumnVector & q, const ColumnVector & qp,
+                                       const ColumnVector & tau_cmd, const ColumnVector & Fext,
+                                       const ColumnVector & Next)
+/*!
+  @brief Joints acceleration.
+
+  The robot dynamics is 
+  \f[
+    B(q)\ddot{q} + C(q,\dot{q})\dot{q} + D\dot{q} + g(q) = \tau - J^T(q)f
+  \f]
+  then the joint acceleration is
+  \f[
+   \ddot{q} = B^{-1}(q)\big(\tau - J^T(q)f - C(q,\dot{q})\dot{q} - D\dot{q} - g(q)\big ) 
+  \f]
+*/
+{
+   ColumnVector qpp(dof);
+   qpp = 0.0;
+   qpp = inertia(q).i()*(tau_cmd-torque(q, qp, qpp, Fext, Next));
+   qpp.Release(); 
+   return qpp;
+}
+
+ReturnMatrix Robot::torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & qpp)
+/*!
+  @brief Joint torque, without contact force, based on Recursive 
+  Newton-Euler formulation.
+*/
+{
+   ColumnVector Fext(3), Next(3);
+   Fext = 0;
+   Next = 0;
+   return torque(q, qp, qpp, Fext, Next);
+}
+
+ReturnMatrix Robot::torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & qpp, const ColumnVector & Fext,
+                           const ColumnVector & Next)
+/*!
+  @brief Joint torque based on Recursive Newton-Euler formulation.
+
+
+  In order to apply the RNE as presented in Murray 86, 
+  let us define the following variables 
+  (referenced in the \f$i^{th}\f$ coordinate frame if applicable):
+
+  \f$\sigma_i\f$ is the joint type; \f$\sigma_i = 1\f$ for a revolute
+  joint and \f$\sigma_i = 0\f$ for a prismatic joint.
+
+  \f$ z_0 = 
+    \left [
+      \begin{array}{ccc}
+         0 & 0 & 1
+      \end{array}
+    \right ]^T\f$
+
+  \f$p_i = 
+    \left [
+      \begin{array}{ccc}
+      a_i & d_i \sin \alpha_i & d_i \cos \alpha_i
+      \end{array}
+    \right ]^T\f$ is the position of the \f$i^{th}\f$ with respect to the \f$i-1^{th}\f$ frame.
+
+    Forward Iterations for \f$i=1, 2, \ldots, n\f$. 
+    Initialize: \f$\omega_0 = \dot{\omega}_0 = 0\f$ and \f$\dot{v}_0 = - g\f$.
+    \f[
+    \omega_i = R_i^T [\omega_{i-1} + \sigma_i z_0 \dot{\theta}_i ] 
+    \f]
+    \f[
+    \dot{\omega}_i = R_i^T  \{ \dot{\omega}_{i-1} + 
+    \sigma_i [z_0 \ddot{\theta}_i + \omega_{i-1} \times (z_0 \dot{\theta}_i )] \} 
+    \f]
+    \f[
+    \dot{v}_i = R_i^T  \{ \dot{v}_{i-1} + 
+    (1 -\sigma_i) [z_0 \ddot{d}_i + 2 \omega_{i-1} \times (z_0 \dot{d}_i )] \} 
+    + \dot{\omega}_i \times p_i + \omega_i \times ( \omega_i \times p_i)
+    \f]
+
+    Backward Iterations for \f$i=n, n-1, \ldots, 1\f$. 
+    Initialize: $f_{n+1} = n_{n+1} = 0$.
+    \f[
+    \dot{v}_{ci} = v_i + \omega_i \times r_i 
+    + \omega_i \times (\omega_i \times r_i) 
+    \f]
+    \f[
+    F_i = m_i \dot{v}_{ci} 
+    \f]
+    \f[
+    N_i = I_{ci} \dot{\omega}_i + \omega_i \times (I_{ci} \omega_i)
+    \f]
+    \f[
+    f_i = R_{i+1} [ f_{i+1} ] + F_{i} 
+    \f]
+    \f[
+    n_i = R_{i+1} [ n_{i+1} ]  + p_{i} \times f_{i} 
+    + N_{i} + r_{i} \times F_{i}
+    \f]
+    \f[
+    \tau_i = \sigma_i n_i^T (R_i^T z_0) 
+    + (1 - \sigma_i) f_i^T (R_i^T z_0)
+    \f]
+*/
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Nrows() != dof) error("qpp has wrong dimension");
+   set_q(q);
+   set_qp(qp);
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         w[i] = Rt*(w[i-1] + z0*qp(i));
+         wp[i] = Rt*(wp[i-1] + z0*qpp(i)
+                     + CrossProduct(w[i-1],z0*qp(i)));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]))
+                 + Rt*(vp[i-1]);
+      } else {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + z0*qpp(i))
+                 + 2.0*CrossProduct(w[i],Rt*z0*qp(i))
+                 + CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      if(i == dof) {
+         f[i] = F[i] + Fext;
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i] + Next;
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = ((z0.t()*links[i].R)*n[i]);
+      else
+         temp = ((z0.t()*links[i].R)*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Im*links[i].Gr*links[i].Gr*qpp(i)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix Robot::torque_novelocity(const ColumnVector & qpp)
+/*!
+  @brief Joint torque. when joint velocity is 0, based on Recursive 
+  Newton-Euler formulation.
+*/
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qpp.Nrows() != dof) error("qpp has wrong dimension");
+
+   vp[0] = 0.0;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         wp[i] = Rt*(wp[i-1] + z0*qpp(i));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + Rt*(vp[i-1]);
+      } else {
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + z0*qpp(i))
+                 + CrossProduct(wp[i],p[i]);
+      }
+      a[i] = CrossProduct(wp[i],links[i].r) + vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] = a[i] * links[i].m;
+      N[i] = links[i].I*wp[i];
+      if(i == dof) {
+         f_nv[i] = F[i];
+         n_nv[i] = CrossProduct(p[i],f_nv[i])
+                   + CrossProduct(links[i].r,F[i]) + N[i];
+      } else {
+         f_nv[i] = links[i+1].R*f_nv[i+1] + F[i];
+         n_nv[i] = links[i+1].R*n_nv[i+1] + CrossProduct(p[i],f_nv[i])
+                   + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = ((z0.t()*links[i].R)*n_nv[i]);
+      else
+         temp = ((z0.t()*links[i].R)*f_nv[i]);
+      ltorque(i) = temp(1,1) + links[i].Im*links[i].Gr*links[i].Gr*qpp(i);
+
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix Robot::G()
+//! @brief Joint torque due to gravity based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+         vp[i] = Rt*(vp[i-1]);
+      else
+         vp[i] = Rt*vp[i-1];
+
+      a[i] = vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      if(i == dof) {
+         f[i] = F[i];
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]);
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]);
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = ((z0.t()*links[i].R)*n[i]);
+      else
+         temp = ((z0.t()*links[i].R)*f[i]);
+      ltorque(i) = temp(1,1);
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix Robot::C(const ColumnVector & qp)
+//! @brief Joint torque due to centrifugal and Corriolis based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+
+   vp[0]=0;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         w[i] = Rt*(w[i-1] + z0*qp(i));
+         wp[i] = Rt*(wp[i-1] + CrossProduct(w[i-1],z0*qp(i)));
+         vp[i] = CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]))
+                 + Rt*(vp[i-1]);
+      } else {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*vp[i-1] + 2.0*CrossProduct(w[i],Rt*z0*qp(i))
+                 + CrossProduct(wp[i],p[i])
+                 + CrossProduct(w[i],CrossProduct(w[i],p[i]));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      if(i == dof) {
+         f[i] = F[i];
+         n[i] = CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i],f[i])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = ((z0.t()*links[i].R)*n[i]);
+      else
+         temp = ((z0.t()*links[i].R)*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot::torque(const ColumnVector & q, const ColumnVector & qp,
+                            const ColumnVector & qpp)
+//! @brief Joint torque, without contact force, based on Recursive Newton-Euler formulation.
+{
+   ColumnVector Fext(3), Next(3);
+   Fext = 0;
+   Next = 0;
+   return torque(q, qp, qpp, Fext, Next);
+}
+
+ReturnMatrix mRobot::torque(const ColumnVector & q, const ColumnVector & qp,
+                            const ColumnVector & qpp, const ColumnVector & Fext_,
+                            const ColumnVector & Next_)
+/*!
+  @brief Joint torque based on Recursive Newton-Euler formulation.
+
+
+  In order to apply the RNE, let us define the following variables 
+  (referenced in the \f$i^{th}\f$ coordinate frame if applicable):
+
+  \f$\sigma_i\f$ is the joint type; \f$\sigma_i = 1\f$ for a revolute
+  joint and \f$\sigma_i = 0\f$ for a prismatic joint.
+
+  \f$ z_0 = 
+    \left [
+      \begin{array}{ccc}
+         0 & 0 & 1
+      \end{array}
+    \right ]^T\f$
+
+  \f$p_i =
+    \left [
+      \begin{array}{ccc}
+      a_{i-1} & -d_i sin \alpha_{i-1} & d_i cos \alpha_{i-1}
+      \end{array}
+    \right ]^T\f$ is the position of the $i^{th}$ with respect to the $i-1^{th}$ frame.
+
+  Forward Iterations for \f$i=1, 2, \ldots, n\f$.  Initialize: 
+  \f$\omega_0 = \dot{\omega}_0 = 0$ and $\dot{v}_0 = - g\f$. 
+
+  \f[
+  \omega_i = R_i^T\omega_{i-1} + \sigma_i z_0\dot{\theta_i} 
+  \f]
+  \f[
+  \dot{\omega}_i = R_i^T\dot{\omega}_{i-1} + \sigma_i
+  R_i^T\omega_{i-1}\times z_0 \dot{\theta}_i + \sigma_iz_0\ddot{\theta}_i
+  \f]
+  \f[
+  \dot{v}_i = R_i^T(\dot{\omega}_{i-1}\times p_i +
+  \omega_{i-1}\times(\omega_{i-1}\times p_i) + \dot{v}_{i-1})
+  + (1 - \sigma_i)(2\omega_i\times z_0 dot{d}_i + z_0\ddot{d}_i)
+  \f]
+
+  Backward Iterations for \f$i=n, n-1, \ldots, 1\f$. Initialize: \f$f_{n+1} = n_{n+1} = 0\f$.
+
+  \f[
+  \dot{v}_{ci} = \dot{\omega}_i\times r_i + 
+  \omega_i\times(\omega_i\times r_i) + v_i 
+  \f]
+  \f[
+  F_i = m_i \dot{v}_{ci} 
+  \f]
+  \f[
+  N_i = I_{ci}\ddot{\omega}_i\ + \omega_i \times I_{ci}\omega_i 
+  \f]
+  \f[
+  f_i = R_{i+1}f_{i+1} + F_i
+  \f]
+  \f[
+  n_i = N_i + R_{i+1} n_{i+1} + r_i \times F_i + p_{i+1}\times R_{i+1}f_{i+1}
+  \f]
+  \f[
+  \tau_i = \sigma_i n_i^T z_0 + (1 - \sigma_i) f_i^T z_0
+  \f]
+*/
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Nrows() != dof) error("qpp has wrong dimension");
+   set_q(q);
+   set_qp(qp);
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i))
+                 + z0*qpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+      } else {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i)+ 2.0*CrossProduct(w[i],z0*qp(i));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+   }
+
+   // Load on last link
+   ColumnVector Fext(3), Next(3);
+   if(fix) // Last link is fix
+   {
+      Fext = links[dof+fix].R*Fext_;
+      Next = links[dof+fix].R*Next_;
+   }
+   else
+   {
+      Fext = Fext_;
+      Next = Next_;
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      if(i == dof) {
+         f[i] = F[i] + Fext;
+         n[i] = CrossProduct(links[i].r,F[i]) + N[i] + Next;
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Im*links[i].Gr*links[i].Gr*qpp(i)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot::torque_novelocity(const ColumnVector & qpp)
+//! @brief Joint torque. when joint velocity is 0, based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+
+   vp[0] = 0.0;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         wp[i] = Rt*wp[i-1] + z0*qpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i]) + vp[i-1]);
+      } else {
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i]))
+                 + z0*qpp(i);
+      }
+      a[i] = CrossProduct(wp[i],links[i].r) + vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      N[i] = links[i].I*wp[i];
+      if(i == dof) {
+         f_nv[i] = F[i];
+         n_nv[i] = CrossProduct(links[i].r,F[i]) + N[i];
+      } else {
+         f_nv[i] = links[i+1].R*f_nv[i+1] + F[i];
+         n_nv[i] = links[i+1].R*n_nv[i+1] + CrossProduct(p[i+1],links[i+1].R*f_nv[i+1])
+                   + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n_nv[i]);
+      else
+         temp = (z0.t()*f_nv[i]);
+      ltorque(i) = temp(1,1) + links[i].Im*links[i].Gr*links[i].Gr*qpp(i);
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot::G()
+//! @brief Joint torque due to gravity based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+         vp[i] = Rt*vp[i-1];
+      else
+         vp[i] = Rt*vp[i-1];
+      a[i] = vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      if(i == dof) {
+         f[i] = F[i];
+         n[i] = CrossProduct(links[i].r,F[i]);
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]);
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1);
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot::C(const ColumnVector & qp)
+//! @brief Joint torque due to centrifugal and Corriolis based on Recursive Newton-Euler formulation.  
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+
+   vp[0] = 0;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0) {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         wp[i] = Rt*wp[i-1] + CrossProduct(Rt*w[i-1],z0*qp(i));
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+      } else {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 +  2.0*CrossProduct(w[i],z0*qp(i));
+      }
+      a[i] = CrossProduct(wp[i],links[i].r)
+             + CrossProduct(w[i],CrossProduct(w[i],links[i].r))
+             + vp[i];
+   }
+
+   for(i = dof; i >= 1; i--) {
+      F[i] =  a[i] * links[i].m;
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]);
+      if(i == dof) {
+         f[i] = F[i];
+         n[i] = CrossProduct(links[i].r,F[i]) + N[i];
+      } else {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1])
+                + CrossProduct(links[i].r,F[i]) + N[i];
+      }
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot_min_para::torque(const ColumnVector & q, const ColumnVector & qp,
+                                     const ColumnVector & qpp)
+//! @brief Joint torque without contact force based on Recursive Newton-Euler formulation.
+{
+   ColumnVector Fext(3), Next(3);
+   Fext = 0;
+   Next = 0;
+   return torque(q, qp, qpp, Fext, Next);
+}
+
+ReturnMatrix mRobot_min_para::torque(const ColumnVector & q, const ColumnVector & qp,
+                                     const ColumnVector & qpp, const ColumnVector & Fext_,
+                                     const ColumnVector & Next_)
+/*!
+  @brief Joint torque based on Recursive Newton-Euler formulation.
+
+  See ReturnMatrix mRobot::torque(const ColumnVector & q, const ColumnVector & qp,
+                                  const ColumnVector & qpp, const ColumnVector & Fext,
+                                  const ColumnVector & Next)
+  for the Recursive Newton-Euler formulation.
+*/
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(q.Nrows() != dof) error("q has wrong dimension");
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+   if(qpp.Nrows() != dof) error("qpp has wrong dimension");
+   set_q(q);
+   set_qp(qp);
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         wp[i] = Rt*(wp[i-1] + CrossProduct(w[i-1],z0*qp(i)))
+                 + z0*qpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + z0*qpp(i)+ 2.0*CrossProduct(w[i],z0*qp(i));
+      }
+   }
+
+   ColumnVector Fext(3), Next(3);
+   if(fix)
+   {
+      Fext = links[dof+fix].R*Fext_;
+      Next = links[dof+fix].R*Next_;
+   }
+   else
+   {
+      Fext = Fext_;
+      Next = Next_;
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc) +
+             CrossProduct(w[i], CrossProduct(w[i], links[i].mc));
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]) +
+             CrossProduct(-vp[i], links[i].mc);
+      if(i == dof)
+      {
+         f[i] = F[i] + Fext;
+         n[i] = N[i] + Next;
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1]) + N[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Im*links[i].Gr*links[i].Gr*qpp(i)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+
+ReturnMatrix mRobot_min_para::torque_novelocity(const ColumnVector & qpp)
+//! @brief Joint torque. when joint velocity is 0, based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qpp.Ncols() != 1 || qpp.Nrows() != dof) error("qpp has wrong dimension");
+
+   vp[0] = 0.0;
+   for(i = 1; i <= dof; i++)
+   {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+      {
+         wp[i] = Rt*wp[i-1] + z0*qpp(i);
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i]) + vp[i-1]);
+      }
+      else
+      {
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i]))
+                 + z0*qpp(i);
+      }
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc);
+      N[i] = links[i].I*wp[i] + CrossProduct(-vp[i], links[i].mc);
+      if(i == dof)
+      {
+         f_nv[i] = F[i];
+         n_nv[i] = N[i];
+      }
+      else
+      {
+         f_nv[i] = links[i+1].R*f_nv[i+1] + F[i];
+         n_nv[i] = links[i+1].R*n_nv[i+1] + CrossProduct(p[i+1],links[i+1].R*f_nv[i+1]) + N[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n_nv[i]);
+      else
+         temp = (z0.t()*f_nv[i]);
+      ltorque(i) = temp(1,1) + links[i].Im*links[i].Gr*links[i].Gr*qpp(i);
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot_min_para::G()
+//! @brief Joint torque due to gravity based on Recursive Newton-Euler formulation.
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+
+   vp[0] = gravity;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+         vp[i] = Rt*vp[i-1];
+      else
+         vp[i] = Rt*vp[i-1];
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = vp[i]*links[i].m;
+      N[i] = CrossProduct(-vp[i], links[i].mc);
+      if(i == dof)
+      {
+         f[i] = F[i];
+         n[i] = N[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1]) + N[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1);
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+ReturnMatrix mRobot_min_para::C(const ColumnVector & qp)
+//! @brief Joint torque due to centrifugal and Corriolis based on Recursive Newton-Euler formulation.  
+{
+   int i;
+   ColumnVector ltorque(dof);
+   Matrix Rt, temp;
+   if(qp.Nrows() != dof) error("qp has wrong dimension");
+   set_qp(qp);
+
+   vp[0] = 0;
+   for(i = 1; i <= dof; i++) {
+      Rt = links[i].R.t();
+      if(links[i].get_joint_type() == 0)
+      {
+         w[i] = Rt*w[i-1] + z0*qp(i);
+         wp[i] = Rt*(wp[i-1] + CrossProduct(w[i-1],z0*qp(i)));
+         vp[i] = Rt*(CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i]))
+                     + vp[i-1]);
+      }
+      else
+      {
+         w[i] = Rt*w[i-1];
+         wp[i] = Rt*wp[i-1];
+         vp[i] = Rt*(vp[i-1] + CrossProduct(wp[i-1],p[i])
+                     + CrossProduct(w[i-1],CrossProduct(w[i-1],p[i])))
+                 + 2.0*CrossProduct(w[i],z0*qp(i));
+      }
+   }
+
+   for(i = dof; i >= 1; i--)
+   {
+      F[i] = vp[i]*links[i].m + CrossProduct(wp[i], links[i].mc) +
+             CrossProduct(w[i], CrossProduct(w[i], links[i].mc));
+      N[i] = links[i].I*wp[i] + CrossProduct(w[i],links[i].I*w[i]) +
+             CrossProduct(-vp[i], links[i].mc);
+      if(i == dof)
+      {
+         f[i] = F[i];
+         n[i] = N[i];
+      }
+      else
+      {
+         f[i] = links[i+1].R*f[i+1] + F[i];
+         n[i] = links[i+1].R*n[i+1] + CrossProduct(p[i+1],links[i+1].R*f[i+1]) + N[i];
+      }
+
+      if(links[i].get_joint_type() == 0)
+         temp = (z0.t()*n[i]);
+      else
+         temp = (z0.t()*f[i]);
+      ltorque(i) = temp(1,1)
+                   + links[i].Gr*(links[i].B*qp(i) + links[i].Cf*sign(qp(i)));
+   }
+
+   ltorque.Release(); return ltorque;
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Motion/roboop/dynamics_sim.cpp
===================================================================
RCS file: Motion/roboop/dynamics_sim.cpp
diff -N Motion/roboop/dynamics_sim.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/dynamics_sim.cpp	14 Jul 2004 02:32:12 -0000	1.2
@@ -0,0 +1,371 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+*/
+
+/*!
+  @file dynamics_sim.cpp
+  @brief Basic dynamics simulation class.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: dynamics_sim.cpp,v 1.2 2004/07/14 02:32:12 ejt Exp $";
+
+
+#include "dynamics_sim.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+Dynamics *Dynamics::instance = 0;
+
+
+/*!
+  @fn Dynamics::Dynamics(Robot_basic *robot)
+  @brief Constructor
+*/
+Dynamics::Dynamics(Robot_basic *robot_): robot(robot_)
+{
+  ndof = 1;
+  dof_fix = 1;
+  if(robot)
+    {
+      ndof = robot->get_dof();
+      dof_fix = ndof + robot->get_fix();
+    }
+
+  q = ColumnVector(ndof); 
+  q = 0;
+  qp = ColumnVector(ndof);
+  qp = 0;
+  qpp = ColumnVector(ndof);
+  qpp = 0;
+  qd = ColumnVector(ndof);
+  qd = 0.0;
+  qpd = ColumnVector(ndof);
+  qpd = 0;
+  tau = ColumnVector(ndof);
+  tau = 0.0;
+  pd = ColumnVector(3); pd = 0;
+  ppd = ColumnVector(3);
+  ppd = 0;
+  pppd = ColumnVector(3);
+  pppd = 0;
+  wd = ColumnVector(3);
+  wd = 0;
+  wpd = ColumnVector(3);
+  wpd = 0;
+  nsteps = 50;
+  to = 0;
+  tf = 0.1;
+  dt = ((tf-to)/nsteps)/4.0;
+  tf_cont = 1;
+
+  first_pass_Kutta = true;
+  instance = this;
+}
+
+Dynamics *Dynamics::Instance()
+/*!
+  @brief A pointer to Dynamics instance. Pointer is 0 if there 
+         is no instance (logic done in Constructor).
+*/
+{
+    return instance;
+}
+
+void Dynamics::set_dof(Robot_basic *robot_)
+/*!
+  @brief Set the degree of freedom.
+
+  Obtain the degree of freedom from Robot_basic pointer. Some vectors
+  will be resize with new current dof value.
+*/
+{
+  ndof = 1;
+  dof_fix = 1;
+    robot = robot_;
+  if(robot)
+    {
+      ndof = robot->get_dof();
+      dof_fix = ndof + robot->get_fix();
+    }
+  q = ColumnVector(ndof); 
+  q = 0;
+  qp = ColumnVector(ndof);
+  qp = 0;
+  qpp = ColumnVector(ndof);
+  qpp = 0;
+  qd = ColumnVector(ndof);
+  qd = 0.0;
+  qpd = ColumnVector(ndof);
+  qpd = 0;
+  tau = ColumnVector(ndof);
+  tau = 0.0;
+  
+  first_pass_Kutta = true;
+}
+
+void Dynamics::set_time_frame(const int nsteps_)
+//! @brief Set the number of iterations.
+{ 
+    nsteps = nsteps_; 
+}
+
+void Dynamics::set_final_time(const double tf)
+//! @brief Set the file time.
+{ 
+    tf_cont = tf; 
+}
+
+void Dynamics::reset_time()
+//! @brief Set the simulation time to the inital time.
+{
+    first_pass_Kutta = true;
+}
+
+short Dynamics::set_controller(const Control_Select & control_)
+//! @brief Set the control variable from the Control_Select reference.
+{
+    control = control_;
+    if(ndof != control.get_dof())
+      {
+	control.type = NONE;
+	cerr << "Dynamics::set_controller: mismatch degree of freedom between robot and controller." << endl;
+	return -1;
+      }
+    return 0;
+}
+
+short Dynamics::set_trajectory(const Trajectory_Select & path_select_)
+//! @brief Set the path_select variable from the Trajectory_Select reference.
+{
+    path_select = path_select_;
+
+    if (control.space_type != path_select.type)
+      {
+	control.type = NONE;
+	path_select.type = NONE;
+	cerr << "Dynamics::set_trajectory: controller space and trajectory space are not compatible.\n" 
+	     << "                          Both should be in joint space or in cartesian space." << endl;
+	return -1;
+      }
+    return 0;
+}
+
+ReturnMatrix Dynamics::set_robot_on_first_point_of_splines()
+/*!
+  @brief Set the robot on first point of trajectory.
+
+  Assigned the robot joints position to the first point of the trajectory 
+  if the latter is expressed in joint space, or assigned the robot joints
+  position via inverse kinematics if the trajectory is expressed in 
+  cartesian space.
+  The function return a message on the console if the format of the 
+  trajectory file is incorrect.
+*/
+{
+  ColumnVector qs(2*ndof);
+  
+  if(path_select.type == JOINT_SPACE)
+    {
+      if(path_select.path.p_pdot(0.0, qd, qpd))
+	cerr << "Dynamics::set_robot_on_first_point_of_spines: invalid joint space path." << endl;
+      else
+	{
+	  tf_cont = path_select.path.get_final_time();
+	  robot->set_q(qd);
+	  qs.SubMatrix(1,ndof,1,1) = qd;
+	  qs.SubMatrix(ndof+1,2*ndof,1,1) = 0;
+	  qs.Release();
+	  return qs;
+	}
+    }
+  else if(path_select.type == CARTESIAN_SPACE) // && quaternion active
+    {
+      if( (path_select.path.p_pdot_pddot(0.0, pd, ppd, pppd) == 0) && 
+	  (path_select.path_quat.quat_w(0.0, quatd, wd) == 0) )
+	{
+	  Matrix Tobj(4,4); Tobj = 0;
+	  Tobj.SubMatrix(1,3,1,3) = quatd.R();
+	  Tobj.SubMatrix(1,3,4,4) = pd;
+	  Tobj(4,4) = 1;
+	  bool converge;
+	  robot->inv_kin(Tobj, 0, converge);
+	  
+	  if(converge)
+	    {
+	      tf_cont = path_select.path.get_final_time();
+	      q = robot->get_q();
+	      qs.SubMatrix(1,ndof,1,1) = q;
+	      qs.SubMatrix(ndof+1,2*ndof,1,1) = 0;
+	      
+	      qs.Release();
+	      return qs;
+	    }
+	}
+      else
+	cerr << "Dynamics::set_robot_on_first_point_of_spines: invalid cartesian path." << endl;
+    }
+  
+  q = robot->get_q();
+  qs.SubMatrix(1,ndof,1,1) = q;
+  qs.SubMatrix(ndof+1,2*ndof,1,1) = 0;
+  qs.Release();
+  return qs;
+}
+
+ReturnMatrix Dynamics::xdot(const Matrix & x)
+/*!
+  @brief Obtain state derivative.
+  @param x: state vector (joint speed and joint velocity).
+
+  The controller torque is applied if any controller has been
+  selected, then the joint acceleration is obtained.
+*/
+{
+   q = x.SubMatrix(1,ndof,1,1);        // joint position from state vecteur
+   qp = x.SubMatrix(ndof+1,2*ndof,1,1);// " "   velocity    "           "
+
+   if(robot)
+   {
+       switch (control.type)
+       {
+	   case PD:
+	       if(path_select.type == JOINT_SPACE)
+	       {
+		   if(path_select.path.p_pdot(time, qd, qpd))
+		   {
+		       xd = qp & qpp;   		   
+		       xd.Release(); 
+		       return xd;
+		   }
+	       }
+	       else if(path_select.type == CARTESIAN_SPACE)
+		   cerr << "Dynamics::xdot: Cartesian path can not be used with CTM controller." << endl;
+
+	       tau = control.pd.torque_cmd(*robot, qd, qpd);
+
+	       break;
+
+	   case CTM:
+	       if(path_select.type == JOINT_SPACE)
+	       {
+		   if(path_select.path.p_pdot(time, qd, qpd))
+		   {
+		       xd = qp & qpp;   		   
+		       xd.Release(); 
+		       return xd;
+		   }
+	       }
+	       else if(path_select.type == CARTESIAN_SPACE)
+		   cerr << "Dynamics::xdot: Cartesian path can not be used with CTM controller." << endl;
+
+	       tau = control.ctm.torque_cmd(*robot, qd, qpd);
+
+	       break;
+
+	   case RRA:
+	       if(path_select.type == CARTESIAN_SPACE)
+	       {
+		   if (path_select.path.p_pdot_pddot(time, pd, ppd, pppd) ||
+		       path_select.path_quat.quat_w(time, quatd, wd)) 
+		   {
+		       xd = qp & qpp;
+		       xd.Release();
+		       return xd;
+		   }
+	       }
+	       else if(path_select.type == JOINT_SPACE)
+		   cerr << "Dynamics::xdot: Joint Space path can not be used with RRA controller." << endl;
+
+	       tau = control.rra.torque_cmd(*robot, pppd, ppd, pd, wpd, wd, quatd, dof_fix, dt);
+	       break;
+	   default:
+	       tau = 0;
+       }
+       qpp = robot->acceleration(q, qp, tau);
+   }
+
+   plot();
+
+   xd = qp & qpp;  // state derivative
+
+   xd.Release(); 
+   return xd;
+}
+
+void Dynamics::Runge_Kutta4_Real_time()
+//! @brief Runge Kutta solver for real time.
+{
+    if(first_pass_Kutta)
+    {
+	h = (tf-to)/nsteps;
+	h2 = h/2.0;
+	time = to;
+	x = set_robot_on_first_point_of_splines();
+	first_pass_Kutta = false;
+	return;
+    }
+
+    k1 = xdot(x) * h;
+    time += h2;
+    k2 = xdot(x+k1*0.5)*h;
+    k3 = xdot(x+k2*0.5)*h;
+    time += h2;
+    k4 = xdot(x+k3)*h;
+    x = x + (k1*0.5+ k2 + k3 + k4*0.5)*(1.0/3.0);
+}
+
+void Dynamics::Runge_Kutta4()
+//! @brief Runge Kutta solver.
+{
+   x = set_robot_on_first_point_of_splines();
+   h = (tf_cont - to)/nsteps;
+   h2 = h/2.0;
+   time = to;
+
+   for (int i = 1; i <= nsteps; i++) {
+           k1 = xdot(x) * h;
+      k2 = xdot(x+k1*0.5)*h;
+      k3 = xdot(x+k2*0.5)*h;
+      k4 = xdot(x+k3)*h;
+      x = x + (k1*0.5+ k2 + k3 + k4*0.5)*(1.0/3.0);
+      time += h;
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/dynamics_sim.h
===================================================================
RCS file: Motion/roboop/dynamics_sim.h
diff -N Motion/roboop/dynamics_sim.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/dynamics_sim.h	23 Jul 2004 21:33:46 -0000	1.3
@@ -0,0 +1,120 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/23: Ethan Tira-Thompson
+    -Made destructor virtual (recommended for any classes with virtual functions
+-------------------------------------------------------------------------------
+*/
+
+
+#ifndef DYNAMICS_SIM_H
+#define DYNAMICS_SIM_H
+
+/*!
+  @file dynamics_sim.h
+  @brief Header file for Dynamics definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_dynamics_sim_rcsid[] = "$Id: dynamics_sim.h,v 1.3 2004/07/23 21:33:46 ejt Exp $";
+
+#include "control_select.h"
+#include "quaternion.h"
+#include "robot.h"
+#include "trajectory.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+/*!
+  @class Dynamics
+  @brief Dynamics simulation handling class.
+*/
+class Dynamics
+{
+public:
+    Dynamics(Robot_basic *robot_);
+		virtual ~Dynamics() {}
+    static Dynamics *Instance();
+
+    void set_dof(Robot_basic *robot_);
+    short set_controller(const Control_Select & x);
+    short set_trajectory(const Trajectory_Select & x);
+    ReturnMatrix set_robot_on_first_point_of_splines();
+    void set_time_frame(const int nsteps);
+    void set_final_time(const double tf);
+    void reset_time();
+    void Runge_Kutta4_Real_time();
+    void Runge_Kutta4();
+
+    virtual void plot(){} //!< Virtual plot functions.
+
+// private:
+    ReturnMatrix xdot(const Matrix & xin);
+
+    bool first_pass_Kutta; //!< First time in all Runge_Kutta4 functions.
+    int ndof,              //!< Degree of freedom.
+        dof_fix,           //!< Degree of freedom + virtual link.
+        nsteps;            //!< Numbers of iterations between.
+    double h,              //!< Runge Kutta temporary variable.
+           h2,             //!< Runge Kutta temporary variable.
+           time,           //!< Time during simulation.
+           to,             //!< Initial simulation time.
+           tf,             //!< Final time used in Runge_Kutta4_Real_time.
+           tf_cont,        //!< Final time used in Runge_Kutta4.
+           dt;             //!< Time frame.
+    Matrix k1,             //!< Runge Kutta temporary variable.
+           k2,             //!< Runge Kutta temporary variable.
+           k3,             //!< Runge Kutta temporary variable.
+           k4,             //!< Runge Kutta temporary variable.
+           x,              //!< Stated vector obtain in Runge Kutta functions.
+           xd;             //!< Statd vector derivative obtaint in xdot function.
+    ColumnVector q,        //!< Joints positions.
+                 qp,       //!< Joints velocities.
+                 qpp,      //!< Joints accelerations.
+                 qd,       //!< Desired joints positions.
+                 qpd,      //!< Desired joints velocities.
+                 tau,      //!< Controller output torque.
+                 pd,       //!< Desired end effector cartesian position.
+                 ppd,      //!< Desired end effector cartesian velocity.
+                 pppd,     //!< Desired end effector cartesian acceleration.
+                 wd,       //!< Desired end effector cartesian angular velocity.
+                 wpd;      //!< Desired end effector cartesian angular acceleration.
+    Quaternion quatd;      //!< Desired orientation express by a quaternion.
+    Control_Select control;        //!< Instance of Control_Select class.
+    Trajectory_Select path_select; //!< Instance of Trajectory_Select class.
+    Robot_basic *robot;            //!< Pointer on Robot_basic class.
+
+    static Dynamics *instance;     //!< Static pointer on Dynamics class.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
Index: Motion/roboop/gnugraph.cpp
===================================================================
RCS file: Motion/roboop/gnugraph.cpp
diff -N Motion/roboop/gnugraph.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/gnugraph.cpp	20 Jul 2004 17:55:24 -0000	1.1
@@ -0,0 +1,758 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Added functions set_plot2d and classe IO_matrix_file.
+
+2003/29/04: Etienne Lachance
+   -Class definitions, functions prototype, ... now in gnugraph.h
+   -Improved class IO_matrix_file.
+   -Class Plot2d, GNUcurve are now using STL string instead of char*.
+   -Added class Plot_graph, to create a graph from a data file.
+   -Replaced all NULL by 0.
+   -Use mkstemp instead of tmpnam in void Plot2d::gnuplot(void).
+
+2003/15/08: Etienne Lachance
+   -The member function IO_matrix_file::write writes data in column of each 
+    variables, instead of only one. This way it is possible to load a dat file
+    in Matlab.
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file gnugraph.cpp
+  @brief Graphics functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: gnugraph.cpp,v 1.1 2004/07/20 17:55:24 ejt Exp $";
+
+#include "gnugraph.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+char *curvetype[] =
+   {"lines",
+    "points",
+    "linespoints",
+    "impulses",
+    "dots",
+    "steps",
+    "boxes"};
+
+
+GNUcurve::GNUcurve(void)
+//!  @brief Constructor.
+{
+   ctype = LINES;
+   clabel = "";
+}
+
+
+GNUcurve::GNUcurve(const Matrix & data, const string & label, int type)
+//!  @brief Constructor.
+{
+   xy = data;
+   if(data.Ncols() > 2) 
+      cerr << "GNUcurve::Warning: Only the first two columns are used in GNUcurve\n";
+
+   ctype = type;
+   clabel = label;
+}
+
+
+GNUcurve::GNUcurve(const GNUcurve & gnuc)
+//!  @brief Copy Constructor.
+{
+   xy = gnuc.xy;
+   ctype = gnuc.ctype;
+   clabel = gnuc.clabel;
+}
+
+
+GNUcurve & GNUcurve::operator=(const GNUcurve & gnuc)
+//!  @brief Overload = operator.
+{
+   xy = gnuc.xy;
+   ctype = gnuc.ctype;
+   clabel = gnuc.clabel;
+
+   return *this;
+}
+
+
+void GNUcurve::dump(void)
+//!  @brief Method to dump the content of a curve to stdout
+{
+   cout << "Curve label: " << clabel.c_str() << "\n";
+   cout << "Curve type:  " << curvetype[ctype] << "\n";
+   cout << "Curve data points: \n";
+   cout << xy;
+   cout << "\n\n";
+}
+
+
+Plot2d::Plot2d(void)
+//!  @brief Constructor.
+{
+   ncurves = 0;
+   try
+   {
+      curves = new GNUcurve[NCURVESMAX];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Plot2d::Plot2d:: new ran out of memory" << endl;
+   }
+
+}
+
+
+Plot2d::~Plot2d(void)
+//!  @brief  Destructor.
+{
+   delete [] curves;
+}
+
+
+void Plot2d::gnuplot(void)
+//!  @brief Creates a GNUplot graphic.
+{
+   int i, strl;
+#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__WATCOMC__)
+   char filename[L_tmpnam];
+#else
+   char filename[] = "tmpfileXXXXXX";
+#endif
+   char * filedata=0;
+   char * wibsl;
+   char bsl = '\\';
+
+#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__WATCOMC__)
+   tmpnam(filename); /* generate a temporary file name */
+#else
+   mkstemp(filename);
+#endif
+   /* replacing \ by / */
+   while((wibsl = strchr(filename,bsl)) != 0) {
+      wibsl[0] = '/';
+   }
+
+   {
+      ofstream fileout(filename); /* write the command file */
+      fileout << gnucommand.c_str();
+      fileout << "set title \"" << title << "\"\n";
+      fileout << "set xlabel \"" << xlabel << "\"\n";
+      fileout << "set ylabel \"" << ylabel << "\"\n";
+      fileout << "plot \\\n";
+      for(i = 0; i < ncurves; i++) {
+         fileout << "\"" << filename << "." << i << "\" ";
+         fileout << "title \"" << curves[i].clabel << "\" ";
+         fileout << "with " << curvetype[curves[i].ctype] << " ";
+         if( i+1 < ncurves){
+            fileout << ", \\\n";
+         }
+      }
+      fileout << "\n";
+   }
+   try
+   {
+      filedata = new char[strlen(filename)+3];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Plot2d::gnuplot:: new ran out of memory" << endl;
+   }
+   strcpy(filedata,filename);
+   strcat(filedata,".");
+   strl = strlen(filedata);
+   for(i = 0; i < ncurves; i++) { /* write the data files */
+      sprintf(&filedata[strl],"%d",i);
+      ofstream fileout(filedata);
+#ifndef _MSC_VER // MSVC++ chokes on the next line !
+      fileout << curves[i].xy;
+#else
+      for(int j = 1; j <= curves[i].xy.Nrows(); j++) {
+         for(int k = 1; k <= curves[i].xy.Ncols(); k++) {
+            fileout << curves[i].xy(j,k) << " ";
+         }
+         fileout << "\n";
+      }
+#endif
+   }
+   /* all command and data files are ready for the call to gnuplot */
+#if defined(__WIN32__) || defined(_WIN32) || defined(__NT__) || defined(__CYGWIN__)
+   /* Windows 95/98/NT/2000 etc */
+   char c[L_tmpnam+15];
+   char *d;
+   HWND hwndm, hwnd;
+   if (WinExec(GNUPLOT, SW_SHOWNORMAL) <= 32) { /* start gnuplot */
+      /* failed */
+      cout << "Cannot find the gnuplot application\n";
+      cout << "Press Enter to continue" << endl;
+      getchar();
+      remove(filename); /* clean up the files and return */
+      for(i = 0; i < ncurves; i++) {
+         sprintf(&filedata[strl],"%d",i);
+         remove(filedata);
+      }
+      delete filedata;
+      return;
+   } else { /* succeed */
+      /* get gnuplot main window handle */
+      hwndm = FindWindow((LPSTR) 0, (LPSTR) "gnuplot");
+   }
+   hwnd= GetWindow(hwndm, GW_CHILD); /* get gnuplot command area handle */
+   if(hwnd == 0) cout << "OUPS!!!\n"; /* something wrong happened */
+   sprintf(c,"load \"%s\" \n",filename); /* load command for the plot */
+
+#ifdef __GNUG__        /* Cygnus Gnu C++ for win32*/
+   char ccygnus[] = "cd \"c:\"\n"; /* this string should reflect
+                                      the drive used to mount / 
+                                      where /tmp is located */
+   d = ccygnus;
+   while(*d != '\0') { /* sending the command through windows messages */
+      SendMessage(hwnd,WM_CHAR,*d,1L);
+      d++;
+   }
+#endif
+   d = c;
+   while(*d != '\0') { /* sending the command through windows messages */
+      SendMessage(hwnd,WM_CHAR,*d,1L);
+      d++;
+   }
+   cout << "Press Enter to continue..." << endl;
+   getchar();
+#else      /*  using a pipe under Unix */
+   FILE *command;
+
+   command = popen(GNUPLOT,"w");
+   fprintf(command,"load \"%s\"\n",filename); fflush(command);
+   fprintf(stderr,"Press Enter to continue...\n"); fflush(stderr);
+   getchar();
+   pclose(command);
+#endif
+   remove(filename);
+   for(i = 0; i < ncurves; i++) {
+      sprintf(&filedata[strl],"%d",i);
+      remove(filedata);
+   }
+   delete filedata;
+}
+
+
+void Plot2d::addcurve(const Matrix & data, const string & label, int type)
+//!  @brief Add a curve on the graphic.
+{
+   ncurves++;
+   if(ncurves <= NCURVESMAX) {
+      curves[ncurves-1] = GNUcurve(data,label,type);
+   } else {
+      cout << "Too many curves in your Plot2d (maximum 10)\n";
+      exit(1);
+   }
+}
+
+void Plot2d::addcommand(const string & gcom)
+//!  @brief Add GNUplot command.
+{
+   gnucommand += gcom;
+}
+
+void Plot2d::settitle(const string & t)
+//!  @brief Set the title.
+{
+   title = t;
+}
+
+void Plot2d::setxlabel(const string & t)
+//!  @brief Set the x axis name.
+{
+   xlabel = t;
+}
+
+void Plot2d::setylabel(const string & t)
+//!  @brief Set the y axis name.
+{
+   ylabel = t;
+}
+
+void Plot2d::dump(void)
+//!  @brief Method to dump the content of Plot2d to stdout
+{
+   cout << "gnuplot commands:\n" << gnucommand.c_str();
+   cout << "Plot title: " << title.c_str() << "\n";
+   cout << "X label:    " << xlabel.c_str() << "\n";
+   cout << "Y label:    " << ylabel.c_str() << "\n";
+   for (int i = 0; i < ncurves; i++) {
+      cout << "\nCurve #" << i << "\n";
+      curves[i].dump();
+   }
+}
+
+
+// ---------------------------------------------------------------------------------------
+
+IO_matrix_file::IO_matrix_file(const string & filename_)
+//!  @brief  Constructor.
+{
+   filename = filename_;
+   position_read = 0;
+   nb_iterations_write = 0;
+   nb_iterations_read = 0;
+   nb_element = 0;
+}
+
+
+short IO_matrix_file::write(const vector<Matrix> & data)
+//!  @brief Write data on disk using a default data name..
+{
+   vector<string> title;
+   string tmp;
+   for(int i = 1; i <= (int)data.size(); i++)
+   {
+      tmp = "data#";  // Provide a default name
+      tmp += i;
+      title.push_back(tmp);
+   }
+
+   return IO_matrix_file::write(data, title);
+}
+
+
+short IO_matrix_file::write(const vector<Matrix> & data, const vector<string> & title)
+/*!
+  @brief Write data on disk.
+  @param data: Data.
+  @param title: Name of each data member (ie: speed, position, ...)
+*/  
+{
+   /*
+   If the file "filename" does not exist yet, created it. The first lines of the file
+   contain the following informations (for each line):
+      1) the number of iterations.
+      2) second line is empty.
+      3) the number(n) of matrix/iteration
+      4) number of rows and number of columns of Matrix 1.
+      5)  "                                         "   i.
+      6)  "                                         "   n.
+      7)---------------------------------   (end of header file)
+
+   example of header file;
+   1120
+       
+   2
+   6 1 titre#1
+   6 1 titre#1
+   ---------------------------------
+   */
+   const char *ptr_filename = filename.c_str(); // transform string to *char
+   if(data.size())
+   {
+      if(!nb_iterations_write)
+      {
+         struct stat buf;
+         if(stat(ptr_filename, &buf) )  // File does not exist
+         {
+            ofstream outvecfile(ptr_filename);
+            if(outvecfile)
+            {
+               outvecfile << "nd_iterations " << nb_iterations_write
+               << "        " << endl;
+               outvecfile << "nb_vector " << data.size() << endl;
+               for(int i = 0; i < (int)data.size(); i++)
+                  outvecfile << "nb_rows " << data[i].Nrows() << "  "
+                  << "nb_cols " << data[i].Ncols() <<  "  "
+                  << title[i] << endl;
+               outvecfile << "---------------------------------\n";
+            }
+            else
+            {
+               cerr << "IO_matrix_file::write: can not open file " << filename.c_str() << endl;
+               return IO_COULD_NOT_OPEN_FILE;
+            }
+         }
+         else
+         {
+            ifstream invecfile(ptr_filename, ios::in);
+            if(invecfile)
+               invecfile >> nb_iterations_write;
+         }
+      }
+
+      ofstream outvecfile(ptr_filename, ios::in | ios::out);
+      if(outvecfile)
+      {
+         outvecfile.seekp(strlen("nb_iterations ")); // position at start of fileObject
+         outvecfile << ++nb_iterations_write << endl;
+         outvecfile.seekp(0, std::ios::end); // position at end of fileObject
+         for(int i = 0; i < (int)data.size(); i++)
+         {
+            for(int j = 1; j <= data[i].Nrows(); j++) {
+               for(int k = 1; k <= data[i].Ncols(); k++) {
+                  outvecfile << data[i](j,k) << " ";
+               }
+            }
+         }
+         outvecfile << endl;
+         outvecfile << endl;
+      }
+      else
+      {
+         cerr << "IO_matrix_file::write: can not open file " << filename.c_str() << endl;
+         return IO_COULD_NOT_OPEN_FILE;
+      }
+   }
+   else
+   {
+      cerr << "IO_matrix_file::write: vector data is empty" << endl;
+      return IO_DATA_EMPTY;
+   }
+
+   return 0;
+}
+
+
+short IO_matrix_file::read(vector<Matrix> & data)
+//! @brief Read one sequence of data per call.
+{
+   vector<string> data_title;
+   string tmp;
+   for(int i = 1; i <= (int)data.size(); i++)
+   {
+      tmp = "data#";  // Provide a default name
+      tmp += i;
+      data_title.push_back(tmp);
+   }
+
+   return IO_matrix_file::read(data, data_title);
+}
+
+
+short IO_matrix_file::read(vector<Matrix> & data, vector<string> & data_title)
+//! @brief Read one sequence of data per call.
+{
+   /*
+   If the file "filename does not exist yet, created it and fill the first line
+   with the number of rows and columns for each element of "data".
+   ex: 6x1;3x1;3x3;
+   This line indidate that data has 3 elements Matrix. The first one has 6 rows and
+   1 columns, the second one has 3 rows and 1 columns ...
+   */
+   static const char *ptr_filename = filename.c_str(); // transform string to *char
+   ifstream invecfile(ptr_filename, ios::in);
+
+   if(invecfile)
+   {
+      if(!position_read)
+      {
+#ifdef __WATCOMC__
+         char temp[256];
+#else
+         string temp;
+#endif
+         int nbcol = 0, nbrow = 0;
+         invecfile >> temp >> nb_iterations_read;
+         invecfile >> temp >> nb_element;
+         Matrix mat_tmp;
+         data.clear();
+         data_title.clear();
+         for(int i = 1; i <= nb_element; i++)
+         {
+            data.push_back(mat_tmp);
+            data_title.push_back(temp);
+         }
+         for(int j = 0; j < nb_element; j++)
+         {
+            invecfile >> temp >> nbrow;
+            invecfile >> temp >> nbcol;
+#ifdef __WATCOMC__
+            invecfile >> temp >> data_title[j];
+#else
+            getline(invecfile,data_title[j]);
+#endif
+            if( (nbrow != data[j].Nrows()) ||
+                  (nbcol != data[j].Ncols()) )
+               data[j] = Matrix(nbrow, nbcol);
+         }
+         invecfile >> temp;  //------------------------
+         position_read = invecfile.tellg();
+      }
+
+      if(position_read > 0)
+      {
+         invecfile.seekg(position_read); // position for reading
+         for(int ii = 0; ii < (int)data.size(); ii++)
+            for(int jj = 1; jj <= data[ii].Nrows(); jj++)
+               for(int kk = 1; kk <= data[ii].Ncols(); kk++)
+                  invecfile >> data[ii](jj,kk);
+
+         position_read = invecfile.tellg(); // position for next reading
+      }
+   }
+   else
+   {
+      cerr << "IO_matrix_file::read, can not open file" << filename.c_str() << endl;
+      return IO_COULD_NOT_OPEN_FILE;
+   }
+   return 0;
+}
+
+
+short IO_matrix_file::read_all(vector<Matrix> & data, vector<string> & data_title)
+/*!
+  @brief Reads all sequences of data.
+  
+   If the file "filename does not exist yet, created it and fill the first line
+   with the number of rows and columns for each element of "data".
+   ex: 6x1;3x1;3x3;
+   This line indidate that data has 3 elements Matrix. The first one has 6 rows and
+   1 columns, the second one has 3 rows and 1 columns ...
+*/
+{
+   static const char *ptr_filename = filename.c_str(); // transform string to *char
+   ifstream invecfile(ptr_filename, ios::in);
+
+   if(invecfile)
+   {
+#ifdef __WATCOMC__
+      char temp[256];
+#else
+      string temp;
+#endif
+      int nbcol = 0, nbrow = 0;
+      invecfile >> temp >> nb_iterations_read;
+      invecfile >> temp >> nb_element;
+
+      Matrix mat_tmp;
+      data.clear();
+      data_title.clear();
+      for(int i = 1; i <= nb_element; i++)
+      {
+         data.push_back(mat_tmp);
+         data_title.push_back(" ");
+      }
+
+      for(int j = 0; j < nb_element; j++)
+      {
+         invecfile >> temp >> nbrow;
+         invecfile >> temp >> nbcol;
+         if(nbcol >1)
+            return IO_MISMATCH_SIZE;
+
+#ifdef __WATCOMC__
+         invecfile >> temp >> data_title[j];
+#else
+         getline(invecfile,data_title[j]);
+#endif
+         if( (nbrow != data[j].Nrows()) ||
+               (nbcol != data[j].Ncols()) )
+            data[j] = Matrix(nbrow, nbcol*nb_iterations_read);
+      }
+      invecfile >> temp;  //---------------------------------
+
+      for(int k = 1; k <= nb_iterations_read; k++)
+         for(int ii = 0; ii < (int)data.size(); ii++)
+            for(int jj = 1; jj <= data[ii].Nrows(); jj++)
+               invecfile >> data[ii](jj,k);
+   }
+   else
+   {
+      cerr << "IO_matrix_file::read_all, can not open file " << filename.c_str() << endl;
+      return IO_COULD_NOT_OPEN_FILE;
+   }
+   return 0;
+}
+
+// ---------------------------------------------------------------------------------------
+
+/*!
+  @fn Plot_file::Plot_file(const string & filename)
+  @brief Constructor.
+
+  Reads all the data of the file filename.
+*/
+Plot_file::Plot_file(const string & filename) : IO_matrix_file(filename), Plot2d()
+{
+   //clear the buffers in case of error while reading the file
+   if(read_all(data_from_file, data_title))
+   {
+      data_from_file.clear();
+      data_title.clear();
+      cerr << "Plot_file::Plot_file: problem in reading file " << filename.c_str() << "." << endl;
+   }
+}
+
+
+short Plot_file::graph(const string & title_graph, const string & label, const short x,
+                       const short y, const short x_start, const short y_start,
+                       const short y_end)
+//!  @brief Creates a graphic.
+{
+   if(data_from_file.size())
+   {
+      if(data_from_file[x].Ncols() != data_from_file[y].Ncols())
+      {
+         cerr << "Plot_file::graph: number of rows of xdata and ydata does not match" << endl;
+         return X_Y_DATA_NO_MATCH;
+      }
+
+      settitle(title_graph.c_str());
+      setxlabel(data_title[x]);
+      setylabel(data_title[y]);
+
+      string legend;
+      for(int i = y_start; i <= y_end; i++)
+      {
+#ifdef __WATCOMC__
+         ostrstream istr;
+         {
+            char temp[256];
+            sprintf(temp,"%d",i-y_start+1);
+            istr << temp;
+         }
+#else
+         ostringstream istr;
+         istr << label << i-y_start+1;
+#endif
+         legend = istr.str();
+
+         addcurve((data_from_file[x].SubMatrix(x_start,x_start,1,data_from_file[x].Ncols())
+                   & data_from_file[y].SubMatrix(i,i,1,data_from_file[y].Ncols())).t(),
+                  legend, POINTS);
+      }
+      gnuplot();
+      return 0;
+   }
+   else
+   {
+      cerr << "Plot_file::graph: data file buffer is empty." << endl;
+      return PROBLEM_FILE_READING;
+   }
+}
+
+// ---------------------------------------------------------------------------------------------
+
+short set_plot2d(const char *title_graph, const char *x_axis_title, const char *y_axis_title,
+                 const char *label, int type, const Matrix &xdata, const Matrix &ydata,
+                 int start_y, int end_y)
+{
+
+   Plot2d plotgraph;
+   char *legend=0;
+   try
+   {
+      legend = new char[strlen(label)+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "set_plot2d:: new ran out of memory" << endl;
+      return OUT_OF_MEMORY;
+   }
+
+   if(xdata.Ncols() != ydata.Ncols())
+   {
+      cerr << "set_plot2d:: number of rows of xdata and ydata does not match" << endl;
+      return X_Y_DATA_NO_MATCH;
+   }
+
+   plotgraph.settitle(title_graph);
+   plotgraph.setxlabel(x_axis_title);
+   plotgraph.setylabel(y_axis_title);
+
+   for(int i = start_y; i <= end_y; i++)
+   {
+      snprintf(legend, sizeof(legend), "%s%d", label, i-start_y+1);
+      plotgraph.addcurve((xdata & ydata.SubMatrix(i,i,1,ydata.Ncols())).t(), legend, type);
+   }
+   plotgraph.gnuplot();
+
+   delete [] legend;
+
+   return 0;
+}
+
+short set_plot2d(const char *title_graph, const char *x_axis_title, const char *y_axis_title,
+                 const vector<char *> label, int type, const Matrix &xdata, const Matrix &ydata,
+                 const vector<int> & data_select)
+{
+   Plot2d plotgraph;
+
+   plotgraph.settitle(title_graph);
+   plotgraph.setxlabel(x_axis_title);
+   plotgraph.setylabel(y_axis_title);
+
+   if(xdata.Ncols() != ydata.Ncols())
+   {
+      cerr << "set_plot2d:: number of rows of xdata and ydata does not match" << endl;
+      return X_Y_DATA_NO_MATCH;
+   }
+   if(data_select.size() != label.size())
+   {
+      cerr << "set_plot2d:: number of labels does not match" << endl;
+      return LABELS_NBR_NO_MATCH;
+   }
+
+   for(int i = 0; i < (int)data_select.size(); i++)
+      plotgraph.addcurve((xdata & ydata.SubMatrix(data_select[i],data_select[i],
+                          1,ydata.Ncols())).t(), label[i], type);
+   plotgraph.gnuplot();
+
+   return 0;
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/gnugraph.h
===================================================================
RCS file: Motion/roboop/gnugraph.h
diff -N Motion/roboop/gnugraph.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/gnugraph.h	20 Jul 2004 17:55:24 -0000	1.1
@@ -0,0 +1,205 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+#ifndef GNUGRAPH_H
+#define GNUGRAPH_H
+
+
+/*!
+  @file gnugraph.h
+  @brief Header file for graphics definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_gnugraph_rcsid[] = "$Id: gnugraph.h,v 1.1 2004/07/20 17:55:24 ejt Exp $";
+
+#if defined(__WIN32__) || defined(_WIN32) || defined(__NT__)  || defined(__CYGWIN__)      /* Windows 95/NT */
+
+#define GNUPLOT "wgnuplot.exe"
+#define STRICT
+#include <windows.h>
+
+#ifdef _MSC_VER 
+#define snprintf	_snprintf
+#endif
+
+#else // Unix 
+
+#define GNUPLOT "gnuplot"
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include "robot.h"
+#include <sys/stat.h>
+
+#ifdef __WATCOMC__
+#include <strstrea.h>
+#else
+#include <sstream>
+#endif
+#include <vector>
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#define OUT_OF_MEMORY       -1
+#define X_Y_DATA_NO_MATCH   -2
+#define LABELS_NBR_NO_MATCH -3
+
+short set_plot2d(const char *title_graph, const char *x_axis_title, const char *y_axis_title,
+                 const char *label, int type, const Matrix &xdata, const Matrix &ydata,
+                 int start_y, int end_y);
+
+short set_plot2d(const char *title_graph, const char *x_axis_title, const char *y_axis_title,
+                 const vector<char *>label, int type, const Matrix &xdata, const Matrix &ydata,
+                 const vector<int> & data_select);
+
+
+//  interface class for gnuplot
+
+#define LINES       0
+#define POINTS      1
+#define LINESPOINTS 2
+#define IMPULSES    3
+#define DOTS        4
+#define STEPS       5
+#define BOXES       6
+
+#define NCURVESMAX  10  // maximum number of curves in the same Plot2d 
+
+class Plot2d;
+
+/*!
+  @class GNUcurve
+  @brief Object for one curve.
+ */
+class GNUcurve {
+   friend class Plot2d; //!< Plot2d need access to private data
+   Matrix xy;           //!< n x 2 matrix defining the curve */
+   string clabel;       //!< string defining the curve label for the legend
+   int ctype;           //!< curve type: lines, points, linespoints, impulses,
+                        //!< dots, steps, boxes
+public:
+   GNUcurve(const Matrix & data, const string & label = "", int type = LINES);
+   GNUcurve(void);
+   GNUcurve(const GNUcurve & gnuc);
+   GNUcurve & operator=(const GNUcurve & gnuc);
+   void dump(void);
+};
+
+
+/*!
+  @class Plot2d
+  @brief 2d plot object.
+*/
+class Plot2d {
+   string 
+     title,           //!< Graph title.
+     xlabel,          //!< Graph x axis.
+     ylabel;          //!< Graph y axis.
+   string gnucommand; //!< GNU plot command.
+   int ncurves;       //!< Number of curves.
+   GNUcurve *curves;  //!< Pointer to GNUcurve object.
+public:
+   Plot2d(void);
+   ~Plot2d(void);
+   void dump(void);
+   void settitle(const string & t);
+   void setxlabel(const string & t);
+   void setylabel(const string & t);
+   void addcurve(const Matrix & data, const string & label = "", int type = LINES);
+   void gnuplot(void);
+   void addcommand(const string & gcom);
+};
+
+#define IO_COULD_NOT_OPEN_FILE  -1
+#define IO_MISMATCH_SIZE        -2
+#define IO_DATA_EMPTY           -3
+#define IO_MISMATCH_ELEMENT_NBR -4
+#define PROBLEM_FILE_READING    -5
+
+
+/*!
+  @class IO_matrix_file.
+  @brief Read and write data at every iterations in a file.
+*/
+class IO_matrix_file {
+public:
+   IO_matrix_file(const string & filename);
+   short write(const vector<Matrix> & data);
+   short write(const vector<Matrix> & data, const vector<string> & title);
+   short read(vector<Matrix> & data);
+   short read(vector<Matrix> & data, vector<string> & title);
+   short read_all(vector<Matrix> & data, vector<string> & data_title);
+private:
+   int 
+     position_read,       //!< Position to read the file.
+     nb_iterations_write, //!< Number of iterations in writing mode.
+     nb_iterations_read,  //!< Number of iterations in reading mode.
+     nb_element;          //!< Number of elements to read or write.
+   string filename;       //!< File name.
+};
+
+
+/*!
+  @class Plot_file
+  @brief Creates a graphic from a data file.
+*/
+class Plot_file : public IO_matrix_file, Plot2d
+{
+public:
+   Plot_file(const string & filename);
+   short graph(const string & title_graph, const string & label, const short x,
+               const short y, const short x_start, const short y_start,
+               const short y_end);
+private:
+   vector<Matrix> data_from_file;  //!< Data file.
+   vector<string> data_title;      //!< Data file title.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
Index: Motion/roboop/homogen.cpp
===================================================================
RCS file: Motion/roboop/homogen.cpp
diff -N Motion/roboop/homogen.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/homogen.cpp	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,306 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added protection on trans function.
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file homogen.cpp
+  @brief Homogen transformation functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: homogen.cpp,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+ReturnMatrix trans(const ColumnVector & a)
+//!  @brief Translation.
+{
+   Matrix translation(4,4);
+
+   translation << fourbyfourident; // identity matrix 
+
+   if (a.Nrows() < 3) 
+     {
+       translation(1,4) = a(1);
+       translation(2,4) = a(2);
+       translation(3,4) = a(3);
+     }
+   else
+       cerr << "trans: wrong size in input vector." << endl;
+
+   translation.Release(); return translation;
+}
+
+
+ReturnMatrix rotx(const Real alpha)
+//!  @brief Rotation around x axis.
+{
+   Matrix rot(4,4);
+   Real c, s;
+
+   rot << fourbyfourident; // identity matrix 
+
+   c = cos(alpha);
+   s = sin(alpha);
+
+   rot(2,2) = c;
+   rot(3,3) = c;
+   rot(2,3) = -s;
+   rot(3,2) = s;
+
+   rot.Release(); return rot;
+}
+
+
+ReturnMatrix roty(const Real beta)
+//!  @brief Rotation around x axis.
+{
+   Matrix rot(4,4);
+   Real c, s;
+
+   rot << fourbyfourident; // identity matrix
+
+   c = cos(beta);
+   s = sin(beta);
+
+   rot(1,1) = c;
+   rot(3,3) = c;
+   rot(1,3) = s;
+   rot(3,1) = -s;
+
+   rot.Release(); return rot;
+}
+
+
+ReturnMatrix rotz(const Real gamma)
+//!  @brief Rotation around z axis.
+{
+   Matrix rot(4,4);
+   Real c, s;
+
+   rot << fourbyfourident; // identity matrix
+
+   c = cos(gamma);
+   s = sin(gamma);
+
+   rot(1,1) = c;
+   rot(2,2) = c;
+   rot(1,2) = -s;
+   rot(2,1) = s;
+
+   rot.Release(); return rot;
+}
+
+// compound rotations 
+
+
+ReturnMatrix rotk(const Real theta, const ColumnVector & k)
+//! @brief Rotation around arbitrary axis.
+{
+   Matrix rot(4,4);
+   Real c, s, vers, kx, ky, kz;
+
+   rot << fourbyfourident; // identity matrix
+
+   vers = SumSquare(k.SubMatrix(1,3,1,1));
+   if (vers != 0.0) { // compute the rotation if the vector norm is not 0.0
+      vers = sqrt(1/vers);
+      kx = k(1)*vers;
+      ky = k(2)*vers;
+      kz = k(3)*vers;
+      s = sin(theta);
+      c = cos(theta);
+      vers = 1-c;
+
+      rot(1,1) = kx*kx*vers+c;
+      rot(1,2) = kx*ky*vers-kz*s;
+      rot(1,3) = kx*kz*vers+ky*s;
+      rot(2,1) = kx*ky*vers+kz*s;
+      rot(2,2) = ky*ky*vers+c;
+      rot(2,3) = ky*kz*vers-kx*s;
+      rot(3,1) = kx*kz*vers-ky*s;
+      rot(3,2) = ky*kz*vers+kx*s;
+      rot(3,3) = kz*kz*vers+c;
+   }
+
+   rot.Release(); return rot;
+}
+
+
+ReturnMatrix rpy(const ColumnVector & a)
+//!  @brief Roll Pitch Yaw rotation.
+{
+   Matrix rot(4,4);
+   Real ca, sa, cb, sb, cc, sc;
+
+   rot << fourbyfourident; // identity matrix
+
+   ca = cos(a(1));
+   sa = sin(a(1));
+   cb = cos(a(2));
+   sb = sin(a(2));
+   cc = cos(a(3));
+   sc = sin(a(3));
+
+   rot(1,1) = cb*cc;
+   rot(1,2) = sa*sb*cc-ca*sc;
+   rot(1,3) = ca*sb*cc+sa*sc;
+   rot(2,1) = cb*sc;
+   rot(2,2) = sa*sb*sc+ca*cc;
+   rot(2,3) = ca*sb*sc-sa*cc;
+   rot(3,1) = -sb;
+   rot(3,2) = sa*cb;
+   rot(3,3) = ca*cb;
+
+   rot.Release(); return rot;
+}
+
+
+ReturnMatrix eulzxz(const ColumnVector & a)
+//!  @brief Euler ZXZ rotation
+{
+   Matrix rot(4,4);
+   Real c1, s1, ca, sa, c2, s2;
+
+   rot << fourbyfourident; // identity matrix
+
+   c1 = cos(a(1));
+   s1 = sin(a(1));
+   ca = cos(a(2));
+   sa = sin(a(2));
+   c2 = cos(a(3));
+   s2 = sin(a(3));
+
+   rot(1,1) = c1*c2-s1*ca*s2;
+   rot(1,2) = -c1*s2-s1*ca*c2;
+   rot(1,3) = sa*s1;
+   rot(2,1) = s1*c2+c1*ca*s2;
+   rot(2,2) = -s1*s2+c1*ca*c2;
+   rot(2,3) = -sa*c1;
+   rot(3,1) = sa*s2;
+   rot(3,2) = sa*c2;
+   rot(3,3) = ca;
+
+   rot.Release(); return rot;
+}
+
+
+ReturnMatrix rotd(const Real theta, const ColumnVector & k1,
+                  const ColumnVector & k2)
+//!  @brief Rotation around an arbitrary line.
+{
+   Matrix rot;
+
+   rot = trans(k1)*rotk(theta,k2-k1)*trans(-k1);
+
+   rot.Release(); return rot;
+}
+
+// inverse problem for compound rotations
+
+ReturnMatrix irotk(const Matrix & R)
+//!  @brief Obtain axis from a rotation matrix.
+{
+   ColumnVector k(4);
+   Real a, b, c;
+
+   a = (R(3,2)-R(2,3));
+   b = (R(1,3)-R(3,1));
+   c = (R(2,1)-R(1,2));
+   k(4) = atan(sqrt(a*a + b*b + c*c)/(R(1,1) + R(2,2) + R(3,3)-1));
+   k(1) = (R(3,2)-R(2,3))/(2*sin(k(4)));
+   k(2) = (R(1,3)-R(3,1))/(2*sin(k(4)));
+   k(3) = (R(2,1)-R(1,2))/(2*sin(k(4)));
+
+   k.Release(); return k;
+}
+
+
+ReturnMatrix irpy(const Matrix & R)
+  //!  @brief Obtain Roll, Pitch and Yaw from a rotation matrix.
+{
+   ColumnVector k(3);
+
+   if (R(3,1)==1) {
+      k(1) = atan2(-R(1,2),-R(1,3));
+      k(2) = -M_PI/2;
+      k(3) = 0.0;
+   } else if (R(3,1)==-1) {
+      k(1) = atan2(R(1,2),R(1,3));
+      k(2) = M_PI/2;
+      k(3) = 0.0;
+   } else {
+      k(1) = atan2(R(3,2), R(3,3));
+      k(2) = atan2(-R(3,1), sqrt(R(1,1)*R(1,1) + R(2,1)*R(2,1)));
+      k(3) = atan2(R(2,1), R(1,1));
+   }
+
+   k.Release(); return k;
+}
+
+
+ReturnMatrix ieulzxz(const Matrix & R)
+  //!  @brief Obtain Roll, Pitch and Yaw from a rotation matrix.
+{
+   ColumnVector  a(3);
+
+   if ((R(3,3)==1)  || (R(3,3)==-1)) {
+      a(1) = 0.0;
+      a(2) = ((R(3,3) == 1) ? 0.0 : M_PI);
+      a(3) = atan2(R(2,1),R(1,1));
+   } else {
+      a(1) = atan2(R(1,3), -R(2,3));
+      a(2) = atan2(sqrt(R(1,3)*R(1,3) + R(2,3)*R(2,3)), R(3,3));
+      a(3) = atan2(R(3,1), R(3,2));
+   }
+
+   a.Release(); return a;
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/invkine.cpp
===================================================================
RCS file: Motion/roboop/invkine.cpp
diff -N Motion/roboop/invkine.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/invkine.cpp	18 Oct 2004 17:01:38 -0000	1.23
@@ -0,0 +1,1693 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/04/19: Vincent Drolet
+   -Added Robot::inv_kin_rhino and Robot::inv_kin_puma member functions.
+
+2004/04/20: Etienne Lachance
+   -Added try, throw, catch statement in Robot::inv_kin_rhino and 
+    Robot::inv_kin_puma in order to avoid singularity.
+
+2004/05/21: Etienne Lachance
+   -Added Doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+    -Fixed warnings regarding atan2 when using float as Real type
+
+2004/07/16: Ethan Tira-Thompson
+    -If USING_FLOAT is set from newmat's include.h, ITOL is 1e-4 instead of 1e-6
+     Motivation was occasional failures to converge when requiring 1e-6
+     precision from floats using prismatic joints with ranges to 100's
+    -A few modifications to support only solving for mobile joints in chain
+    -Can now do inverse kinematics for frames other than end effector
+
+2004/07/21: Ethan Tira-Thompson
+    -Added inv_kin_pos() for times when you only care about position
+    -Added inv_kin_orientation() for times when you only care about orientation
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file invkine.cpp
+  @brief Inverse kinematics solutions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: invkine.cpp,v 1.23 2004/10/18 17:01:38 ejt Exp $";
+
+#include "robot.h"
+#include <sstream>
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#define NITMAX 1000  //!< def maximum number of iterations in inv_kin 
+#ifdef USING_FLOAT //from newmat's include.h
+#  define ITOL   1e-4f //!< def tolerance for the end of iterations in inv_kin 
+#else
+#  define ITOL   1e-6  //!< def tolerance for the end of iterations in inv_kin 
+#endif
+
+ReturnMatrix Robot_basic::inv_kin(const Matrix & Tobj, const int mj)
+//!  @brief Overload inv_kin function.
+{
+   bool converge = false;
+   return inv_kin(Tobj, mj, dof, converge);
+}
+
+
+ReturnMatrix Robot_basic::inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Numerical inverse kinematics.
+
+  @param Tobj: Transformation matrix expressing the desired end effector pose.
+  @param mj: Select algorithm type, 0: based on Jacobian, 1: based on derivative of T.
+  @param endlink: the link to pretend is the end effector 
+  @param converge: Indicate if the algorithm converge.
+
+  The joint position vector before the inverse kinematics is returned if the 
+  algorithm does not converge.
+*/
+{
+   ColumnVector qout, dq, q_tmp;
+   UpperTriangularMatrix U;
+
+   qout = get_available_q();
+   if(qout.nrows()==0) {
+      converge=true;
+      return qout;
+   }
+   q_tmp = qout;
+
+   converge = false;
+   if(mj == 0) {  // Jacobian based
+      Matrix Ipd, A, B(6,1), M;
+      for(int j = 1; j <= NITMAX; j++) {
+         Ipd = (kine(endlink)).i()*Tobj;
+         B(1,1) = Ipd(1,4);
+         B(2,1) = Ipd(2,4);
+         B(3,1) = Ipd(3,4);
+         B(4,1) = Ipd(3,2);
+         B(5,1) = Ipd(1,3);
+         B(6,1) = Ipd(2,1);
+         A = jacobian(endlink,endlink);
+         QRZ(A,U);
+         QRZ(A,B,M);
+         dq = U.i()*M;
+
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(int k = 1; k<= dq.nrows(); k++)
+            qout(k)+=dq(k);
+         set_q(qout);
+
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   } else {  // using partial derivative of T
+      int adof=get_available_dof(endlink);
+      Matrix A(12,adof),B,M;
+      for(int j = 1; j <= NITMAX; j++) {
+         B = (Tobj-kine(endlink)).SubMatrix(1,3,1,4).AsColumn();
+         int k=1;
+         for(int i = 1; i<=dof && k<=adof; i++) {
+            if(links[i].immobile)
+               continue;
+            A.SubMatrix(1,12,k,k) = dTdqi(i,endlink).SubMatrix(1,3,1,4).AsColumn();
+            k++;
+         }
+         if(A.ncols()==0) {
+            converge=true;
+            break;
+         }
+         QRZ(A,U);
+         QRZ(A,B,M);
+         dq = U.i()*M;
+
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(k = 1; k<=adof; k++)
+            qout(k)+=dq(k);
+         set_q(qout);
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   }
+
+   if(converge)
+   {
+      // Make sure that: -pi < qout <= pi for revolute joints
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+      {
+         if(links[i].immobile)
+            continue;
+         if(links[i].get_joint_type() == 0) {
+            while(qout(j) >= M_PI)
+               qout(j) -= 2*M_PI;
+            while(qout(j) <= -M_PI)
+               qout(j) += 2*M_PI;
+         }
+         j++;
+      }
+      set_q(qout);
+      qout.Release();
+      return qout;
+   }
+   else
+   {
+      set_q(q_tmp);
+      q_tmp.Release();
+      return q_tmp;
+   }
+}
+
+
+//void serrprintf(const char *, int a, int b, int c);
+//#define DEBUG_ET { int debl=deb++; for(int a=0; a<50; a++) serrprintf("%d: %d %d\n",a,debl,__LINE__); }
+#define DEBUG_ET ;
+
+//cerr << a << ": " << debl << ' ' << __LINE__ << endl; }
+
+ReturnMatrix Robot_basic::inv_kin_pos(const ColumnVector & Pobj, const int mj, const int endlink, const ColumnVector& /*Plink*/, bool & converge)
+/*!
+  @brief Numerical inverse kinematics.
+
+  @param Pobj: Vector expressing the desired end effector position; can be homogenous
+  @param mj: Select algorithm type, 0: based on Jacobian, 1: based on derivative of T.
+  @param endlink: the link to pretend is the end effector 
+  @param Plink: ignored for now
+  @param converge: Indicate if the algorithm converge.
+
+  The joint position vector before the inverse kinematics is returned if the 
+  algorithm does not converge.
+*/
+{
+   ColumnVector qout, dq, q_tmp;
+   UpperTriangularMatrix U;
+   //int deb=0;
+	 DEBUG_ET;
+
+   qout = get_available_q();
+   if(qout.nrows()==0) {
+      converge=true;
+      return qout;
+   }
+   q_tmp = qout;
+
+   ColumnVector PHobj(4);
+   if(Pobj.nrows()!=4) {
+      PHobj.SubMatrix(1,Pobj.nrows(),1,1)=Pobj;
+      PHobj.SubMatrix(Pobj.nrows()+1,4,1,1)=1;
+   } else {
+      PHobj=Pobj;
+   }
+
+	 DEBUG_ET;
+   converge = false;
+   if(mj == 0) {  // Jacobian based
+   DEBUG_ET;
+      Matrix Ipd, A, B(3,1),M;
+      for(int j = 1; j <= NITMAX; j++) {
+         Ipd = (kine(endlink)).i()*PHobj;
+         B(1,1) = Ipd(1,1);
+         B(2,1) = Ipd(2,1);
+         B(3,1) = Ipd(3,1);
+         A = jacobian(endlink,endlink);
+         A = A.SubMatrix(1,3,1,A.ncols());
+         //need to remove any joints which do not affect position
+         //otherwise those joints's q go nuts
+         int removeCount=0;
+         for(int k=1; k<= A.ncols(); k++)
+            if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()<ITOL)
+               removeCount++;
+         Matrix A2(3,A.ncols()-removeCount);
+         if(removeCount==0)
+            A2=A;
+         else
+            for(int k=1,m=1; k<= A.ncols(); k++) {
+               if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()<ITOL)
+                  continue;
+               A2.SubMatrix(1,3,m,m)=A.SubMatrix(1,3,k,k);
+               m++;
+            }
+         //ok... on with the show, using A2 now
+         if(A2.ncols()==0) {
+            converge=true;
+            break;
+         }
+				 {
+					 stringstream ss;
+					 ss << "A2-pre:\n";
+					 for(int r=1; r<=A2.nrows(); r++) {
+						 for(int c=1; c<=A2.ncols(); c++) {
+							 ss << A2(r,c) << ' ';
+						 }
+						 ss << '\n';
+					 }
+         QRZ(A2,U);
+				 /*	 ss << "A2-mid:\n";
+	 for(int r=1; r<=A2.nrows(); r++) {
+		 for(int c=1; c<=A2.ncols(); c++) {
+			 ss << A2(r,c) << ' ';
+		 }
+		 ss << '\n';
+		 }*/
+         QRZ(A2,B,M);
+         //serrprintf(ss.str().c_str(),0,0,0);
+			}
+   DEBUG_ET;
+   /*stringstream ss;
+	 ss << "A2-post:\n";
+	 for(int r=1; r<=A2.nrows(); r++) {
+		 for(int c=1; c<=A2.ncols(); c++) {
+			 ss << A2(r,c) << ' ';
+		 }
+		 ss << '\n';
+	 }
+	 ss << "U:\n";
+	 for(int r=1; r<=4; r++) {
+		 for(int c=r; c<=4; c++) {
+			 ss << U(r,c) << ' ';
+		 }
+		 ss << '\n';
+	 }
+	 ss << "M: ";
+	 for(int r=1; r<=M.nrows(); r++) {
+		 ss << M(r,1) << ' ';
+	 }
+	 ss << '\n';*/
+	 //serrprintf(ss.str().c_str(),0,0,0);
+
+   DEBUG_ET;
+         dq = U.i()*M;
+
+   DEBUG_ET;
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(int k = 1,m=1; m<= dq.nrows(); k++)
+            if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()>=ITOL)
+               qout(k)+=dq(m++);
+         set_q(qout);
+
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   } else {  // using partial derivative of T
+      int adof=get_available_dof(endlink);
+      Matrix A(3,adof),Rcur,B,M;
+      ColumnVector pcur;
+      bool used[adof];
+      for(int j = 1; j <= NITMAX; j++) {
+         kine(Rcur,pcur,endlink);
+         B = (PHobj.SubMatrix(1,3,1,1)-pcur);
+         int k=1,m=1;
+         for(int i = 1; m<=adof; i++) {
+            if(links[i].immobile)
+               continue;
+            Matrix Atmp=dTdqi(i,endlink).SubMatrix(1,3,4,4);
+            used[m]=(Atmp.MaximumAbsoluteValue()>=ITOL);
+            if(!used[m++])
+               continue;
+            A.SubMatrix(1,3,k,k) = Atmp;
+            k++;
+         }
+         Matrix A2=A.SubMatrix(1,3,1,k-1);
+         if(A2.ncols()==0) {
+            converge=true;
+            break;
+         }
+         QRZ(A2,U);
+         QRZ(A2,B,M);
+         dq = U.i()*M;
+
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(k = m = 1; k<=adof; k++)
+            if(used[k])
+               qout(k)+=dq(m++);
+         set_q(qout);
+
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   }
+	 DEBUG_ET;
+
+   if(converge)
+   {
+	 DEBUG_ET;
+      // Make sure that: -pi < qout <= pi for revolute joints
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+      {
+         if(links[i].immobile)
+            continue;
+				 unsigned int * test=(unsigned int*)&qout(j);
+				 if(((*test)&(255U<<23))==(255U<<23)) {
+				   //serrprintf("qout %d is not-finite\n",j,0,0);
+					 set_q(q_tmp);
+					 q_tmp.Release();
+					 return q_tmp;
+				 }
+				 /*
+         if(links[i].get_joint_type() == 0 && finite(qout(j))) {
+            while(qout(j) >= M_PI)
+               qout(j) -= 2*M_PI;
+            while(qout(j) <= -M_PI)
+               qout(j) += 2*M_PI;
+         }
+				 */
+         j++;
+      }
+	 DEBUG_ET;
+      set_q(qout);
+      qout.Release();
+	 DEBUG_ET;
+      return qout;
+   }
+   else
+   {
+	 DEBUG_ET;
+      set_q(q_tmp);
+      q_tmp.Release();
+	 DEBUG_ET;
+      return q_tmp;
+   }
+}
+
+ReturnMatrix Robot_basic::inv_kin_orientation(const Matrix & Robj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Numerical inverse kinematics.
+
+  @param Robj: Rotation matrix expressing the desired end effector orientation w.r.t base frame
+  @param mj: Select algorithm type, 0: based on Jacobian, 1: based on derivative of T.
+  @param endlink: the link to pretend is the end effector 
+  @param converge: Indicate if the algorithm converge.
+
+  The joint position vector before the inverse kinematics is returned if the 
+  algorithm does not converge.
+*/
+{
+   ColumnVector qout, dq, q_tmp;
+   UpperTriangularMatrix U;
+
+   qout = get_available_q();
+   if(qout.nrows()==0) {
+      converge=true;
+      return qout;
+   }
+   q_tmp = qout;
+
+   Matrix RHobj(4,3);
+   RHobj.SubMatrix(1,3,1,3)=Robj;
+   RHobj.SubMatrix(4,4,1,3)=0;
+
+   converge = false;
+   if(mj == 0) {  // Jacobian based
+      Matrix Ipd, A, B(3,1),M;
+      for(int j = 1; j <= NITMAX; j++) {
+         Ipd = kine(endlink).i()*RHobj;
+         B(1,1) = Ipd(3,2);
+         B(2,1) = Ipd(1,3);
+         B(3,1) = Ipd(2,1);
+         A = jacobian(endlink,endlink);
+         A = A.SubMatrix(4,6,1,A.ncols());
+         //need to remove any joints which do not affect position
+         //otherwise those joints's q go nuts
+         int removeCount=0;
+         for(int k=1; k<= A.ncols(); k++)
+            if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()<ITOL)
+               removeCount++;
+         Matrix A2(3,A.ncols()-removeCount);
+         if(removeCount==0)
+            A2=A;
+         else
+            for(int k=1,m=1; k<= A.ncols(); k++) {
+               if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()<ITOL)
+                  continue;
+               A2.SubMatrix(1,3,m,m)=A.SubMatrix(1,3,k,k);
+               m++;
+            }
+         //ok... on with the show, using A2 now
+         if(A2.ncols()==0) {
+            converge=true;
+            break;
+         }
+         QRZ(A2,U);
+         QRZ(A2,B,M);
+         dq = U.i()*M;
+
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(int k = 1,m=1; m<= dq.nrows(); k++)
+            if(A.SubMatrix(1,3,k,k).MaximumAbsoluteValue()>=ITOL)
+               qout(k)+=dq(m++);
+         set_q(qout);
+
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   } else {  // using partial derivative of T
+      int adof=get_available_dof(endlink);
+      Matrix A(9,adof),Rcur,B,M;
+      ColumnVector pcur;
+      bool used[adof];
+      for(int j = 1; j <= NITMAX; j++) {
+         kine(Rcur,pcur,endlink);
+         B = (Robj-Rcur).AsColumn();
+         int k=1,m=1;
+         for(int i = 1; m<=adof; i++) {
+            if(links[i].immobile)
+               continue;
+            Matrix Atmp=dTdqi(i,endlink).SubMatrix(1,3,1,3).AsColumn();
+            used[m]=(Atmp.MaximumAbsoluteValue()>=ITOL);
+            if(!used[m++])
+               continue;
+            A.SubMatrix(1,9,k,k) = Atmp;
+            k++;
+         }
+         Matrix A2=A.SubMatrix(1,9,1,k-1);
+         if(A2.ncols()==0) {
+            converge=true;
+            break;
+         }
+         QRZ(A2,U);
+         QRZ(A2,B,M);
+         dq = U.i()*M;
+
+         while(dq.MaximumAbsoluteValue() > 1)
+            dq /= 10;
+
+         for(k = m = 1; k<=adof; k++)
+            if(used[k])
+               qout(k)+=dq(m++);
+         set_q(qout);
+         
+         if (dq.MaximumAbsoluteValue() < ITOL)
+         {
+            converge = true;
+            break;
+         }
+      }
+   }
+
+   if(converge)
+   {
+      // Make sure that: -pi < qout <= pi for revolute joints
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+      {
+         if(links[i].immobile)
+            continue;
+         if(links[i].get_joint_type() == 0) {
+            while(qout(j) >= M_PI)
+               qout(j) -= 2*M_PI;
+            while(qout(j) <= -M_PI)
+               qout(j) += 2*M_PI;
+         }
+         j++;
+      }
+      set_q(qout);
+      qout.Release();
+      return qout;
+   }
+   else
+   {
+      set_q(q_tmp);
+      q_tmp.Release();
+      return q_tmp;
+   }
+}
+
+// ---------------------  R O B O T   DH   N O T A T I O N  --------------------------
+
+ReturnMatrix Robot::inv_kin(const Matrix & Tobj, const int mj)
+//!  @brief Overload inv_kin function.
+{
+   bool converge = false;
+   return inv_kin(Tobj, mj, dof, converge);
+}
+
+
+ReturnMatrix Robot::inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Inverse kinematics solutions.
+
+  The solution is based on the analytic inverse kinematics if robot type (familly)
+  is Rhino or Puma, otherwise used the numerical algoritm defined in Robot_basic
+  class.
+*/
+{
+   switch (robotType) {
+      case RHINO:
+         return inv_kin_rhino(Tobj, converge);
+      case PUMA:
+         return inv_kin_puma(Tobj, converge);
+      case ERS_LEG:
+      case ERS2XX_HEAD:
+      case ERS7_HEAD:
+         //no specializations yet... :(
+      default:
+         return Robot_basic::inv_kin(Tobj, mj, endlink, converge);
+   }
+}
+
+ReturnMatrix Robot::inv_kin_pos(const ColumnVector & Pobj, const int mj, const int endlink, const ColumnVector& Plink, bool & converge)
+/*!
+  @brief Inverse kinematics solutions.
+
+  The solution is based on the analytic inverse kinematics if robot type (familly)
+  is Rhino or Puma, otherwise used the numerical algoritm defined in Robot_basic
+  class.
+*/
+{
+   switch (robotType) {
+      case ERS_LEG:
+      case ERS2XX_HEAD:
+      case ERS7_HEAD:
+         return inv_kin_ers_pos(Pobj, endlink, Plink, converge);
+      case RHINO:
+      case PUMA:
+         //no specializations yet... :(
+      default:
+         return Robot_basic::inv_kin_pos(Pobj, mj, endlink, Plink, converge);
+   }
+}
+
+ReturnMatrix Robot::inv_kin_orientation(const Matrix & Robj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Inverse kinematics solutions.
+
+  The solution is based on the analytic inverse kinematics if robot type (familly)
+  is Rhino or Puma, otherwise used the numerical algoritm defined in Robot_basic
+  class.
+*/
+{
+   switch (robotType) {
+      case ERS_LEG:
+      case ERS2XX_HEAD:
+      case ERS7_HEAD:
+      case RHINO:
+      case PUMA:
+         //no specializations yet... :(
+      default:
+         return Robot_basic::inv_kin_orientation(Robj, mj, endlink, converge);
+   }
+}
+
+
+
+ReturnMatrix Robot::inv_kin_rhino(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Rhino inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(5), q_actual;    
+    q_actual = get_q();
+
+    try
+    {
+	Real theta[6] , diff1, diff2, tmp,
+	     angle , L=0.0 , M=0.0 , K=0.0 , H=0.0 , Gl=0.0 ;
+    
+	// Calcul les deux angles possibles
+	theta[0] = atan2(Tobj(2,4),
+			 Tobj(1,4));
+	
+	theta[1] = atan2(-Tobj(2,4),
+			 -Tobj(1,4))  ;
+	
+	diff1 = fabs(q_actual(1)-theta[0]) ;		
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)		   
+	    theta[1] = theta[0] ;
+	
+	theta[5] = atan2(sin(theta[1])*Tobj(1,1) - cos(theta[1])*Tobj(2,1), 
+			 sin(theta[1])*Tobj(1,2) - cos(theta[1])*Tobj(2,2));
+	
+	// angle = theta1 +theta2 + theta3
+	angle = atan2(-1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3),
+		      -1*Tobj(3,3));
+	
+	L = cos(theta[1])*Tobj(1,4) + 
+	    sin(theta[1])*Tobj(2,4) + 
+	    links[5].d*sin(angle) - 
+	    links[4].a*cos(angle);
+	M = links[1].d - 
+	    Tobj(3,4) - 
+	    links[5].d*cos(angle) - 
+	    links[4].a*sin(angle);
+	K = (L*L + M*M - links[3].a*links[3].a - 
+	     links[2].a*links[2].a) / 
+	    (2 * links[3].a * links[2].a);
+	
+	tmp = 1-K*K;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	theta[0] = atan2( sqrt(tmp) , K );
+	theta[3] = atan2( -sqrt(tmp) , K );	
+	
+	diff1 = fabs(q_actual(3)-theta[0]) ;
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	if (diff1 < diff2)
+	    theta[3] = theta[0] ;
+	
+	H = cos(theta[3]) * links[3].a + links[2].a;
+	Gl = sin(theta[3]) * links[3].a;
+	
+	theta[2] = atan2( M , L ) - atan2( Gl , H );
+	theta[4] = atan2( -1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3) , 
+			  -1*Tobj(3,3)) - theta[2] - theta[3] ;
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	set_q(qout);
+	
+	converge = true;
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+
+ReturnMatrix Robot::inv_kin_puma(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Puma inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(6), q_actual;
+    q_actual = get_q();
+
+    try
+    {  
+	Real theta[7] , diff1, diff2, tmp,
+	     A = 0.0 , B = 0.0 , Cl = 0.0 , D =0.0, Ro = 0.0,
+	     H = 0.0 , L = 0.0 , M = 0.0;
+	
+// Removed d6 component because in the Puma inverse kinematics solution 
+// d6 = 0. 
+	if (links[6].d)
+	{
+	    ColumnVector tmpd6(3);
+	    tmpd6(1)=0; tmpd6(2)=0; tmpd6(3)=links[6].d;
+	    tmpd6 = Tobj.SubMatrix(1,3,1,3)*tmpd6;
+	    Tobj.SubMatrix(1,3,4,4) = Tobj.SubMatrix(1,3,4,4) - tmpd6;
+	}
+
+	tmp = Tobj(2,4)*Tobj(2,4) + Tobj(1,4)*Tobj(1,4);
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	Ro = sqrt(tmp);
+	D = (links[2].d+links[3].d) / Ro;
+	
+	tmp = 1-D*D;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	//Calcul les deux angles possibles
+	theta[0] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D, sqrt(tmp));	 
+	//Calcul les deux angles possibles
+	theta[1] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D , -sqrt(tmp));
+	
+	diff1 = fabs(q_actual(1)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[1] = theta[0];
+	
+	tmp = links[3].a*links[3].a + links[4].d*links[4].d;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	Ro = sqrt(tmp);
+	B = atan2(links[4].d,links[3].a);
+	Cl = Tobj(1,4)*Tobj(1,4) + 
+	     Tobj(2,4)*Tobj(2,4) + 
+	     Tobj(3,4)*Tobj(3,4) - 
+	     (links[2].d + links[3].d)*(links[2].d + links[3].d) - 
+	     links[2].a*links[2].a - 
+	     links[3].a*links[3].a - 
+	     links[4].d*links[4].d; 
+	A = Cl / (2*links[2].a);
+	
+	tmp = 1-A/Ro*A/Ro;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	theta[0] = atan2(sqrt(tmp) , A/Ro) + B;
+	theta[3] = atan2(-sqrt(tmp) , A/Ro) + B;
+	
+	diff1 = fabs(q_actual(3)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	//Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[3] = theta[0];
+	
+	H = cos(theta[1])*Tobj(1,4) + sin(theta[1])*Tobj(2,4);
+	L = sin(theta[3])*links[4].d + cos(theta[3])*links[3].a + links[2].a;
+	M = cos(theta[3])*links[4].d - sin(theta[3])*links[3].a;
+	
+	theta[2] = atan2( M , L ) - atan2(Tobj(3,4) , H );
+	
+	theta[0] = atan2( -sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3) , 
+			  cos(theta[2] + theta[3]) * 
+			  (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			  - (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[4] = atan2(-1*(-sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3)), 
+			 -cos(theta[2] + theta[3]) * 
+			 (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			 + (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	diff1 = fabs(q_actual(4)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(4)-theta[4]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[4] = theta[0];
+	
+	theta[5] = atan2( cos(theta[4]) * 
+			  ( cos(theta[2] + theta[3]) * 
+			    (cos(theta[1]) * Tobj(1,3) 
+			     + sin(theta[1])*Tobj(2,3)) 
+			    - (sin(theta[2]+theta[3])*Tobj(3,3)) ) + 
+			  sin(theta[4])*(-sin(theta[1])*Tobj(1,3) 
+					 + cos(theta[1])*Tobj(2,3)) , 
+			  sin(theta[2]+theta[3]) * (cos(theta[1]) * Tobj(1,3) 
+						    + sin(theta[1])*Tobj(2,3) ) 
+			  + (cos(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[6] = atan2( -sin(theta[4]) 
+			  * ( cos(theta[2] + theta[3]) * 
+			      (cos(theta[1]) * Tobj(1,1) 
+			       + sin(theta[1])*Tobj(2,1)) 
+			      - (sin(theta[2]+theta[3])*Tobj(3,1))) + 
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,1) 
+					 + cos(theta[1])*Tobj(2,1)), 
+			  -sin(theta[4]) * ( cos(theta[2] + theta[3]) * 
+					     (cos(theta[1]) * Tobj(1,2) 
+					      + sin(theta[1])*Tobj(2,2)) 
+					     - (sin(theta[2]+theta[3])*Tobj(3,2))) +
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,2) 
+					 + cos(theta[1])*Tobj(2,2)) );
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	qout(6) = theta[6];
+	set_q(qout);
+	
+	converge = true; 
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+ReturnMatrix Robot::inv_kin_ers_pos(const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool & converge) {
+   bool converges[3];
+   
+   bool third_invert=(robotType==ERS7_HEAD || robotType==ERS2XX_HEAD);
+   bool second_invert=false;
+
+   if(endlink>=2) {
+      if(endlink>=3) {
+         if(endlink>=4)
+            set_q(computeThirdERSLink(4,Pobj,endlink,Plink,third_invert,links[4].get_theta_min(),links[4].get_theta_max(),converges[2]),4);
+         set_q(computeSecondERSLink(3,Pobj,endlink,Plink,second_invert,links[3].get_theta_min(),links[3].get_theta_max(),converges[1]),3);
+      }
+      set_q(computeFirstERSLink(2,Pobj,endlink,Plink,links[2].get_theta_min(),links[2].get_theta_max(),converges[0]),2);
+   }
+   
+   //check if link 2 is maxed out
+   if(!converges[0]) {
+      //redo links 3 and 4 since link 2 was limited
+      if(endlink>=3) {
+         if(endlink>=4)
+            set_q(computeSecondERSLink(4,Pobj,endlink,Plink,second_invert,links[4].get_theta_min(),links[4].get_theta_max(),converges[2]),4);
+         set_q(computeFirstERSLink(3,Pobj,endlink,Plink,links[3].get_theta_min(),links[3].get_theta_max(),converges[1]),3);
+      }
+   }
+   
+   //check again, maybe now link 3 is maxed out as well
+   if(!converges[1] && endlink>=4) {
+      //redo link 4 since link 3 was limited
+      set_q(computeFirstERSLink(4,Pobj,endlink,Plink,links[4].get_theta_min(),links[4].get_theta_max(),converges[2]),4);
+   }
+   
+   converge=converges[0] && converges[1] && converges[2];
+   return get_q();
+}
+
+Real Robot::computeFirstERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, Real min, Real max, bool & converge) {
+   //Convert Pobj and Plink to be frame 'curlink' relative
+   ColumnVector po=convertFrame(0,curlink)*Pobj;
+   ColumnVector pl=convertLink(endlink,curlink)*Plink;
+	 if(fabs(pl(1))<ITOL && fabs(pl(2))<ITOL) {
+		 //Plink is along axis of rotation - nothing we do is going to move it, so don't move at all
+		 converge=false; //debatable
+		 return links[curlink].get_q();
+	 }
+   Real to=atan2(po(2),po(1));
+   Real tl=atan2(pl(2),pl(1));
+   Real qtgt=normalize_angle(to-tl);
+   Real qans=limit_angle(qtgt,min,max);
+   converge=(qtgt==qans);
+   return qans;
+}
+
+Real Robot::computeSecondERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool invert, Real min, Real max, bool & converge) {
+	 if(Plink(4)==0) //infinite ray
+		 return computeFirstERSLink(curlink,Pobj,endlink,Plink,min,max,converge);
+   //Convert Pobj, Plink, z3 to be frame 'curlink' relative
+   ColumnVector po=convertFrame(0,curlink)*Pobj;
+   ColumnVector pl=convertLink(endlink,curlink)*Plink;
+	 if(fabs(pl(1))<ITOL && fabs(pl(2))<ITOL) {
+		 //Plink is along axis of rotation - nothing we do is going to move it, so don't move at all
+		 converge=false; //debatable
+		 return links[curlink].get_q();
+	 }
+   Matrix Rp;
+   ColumnVector pp;
+   convertFrame(Rp,pp,curlink-1,curlink);
+   ColumnVector zp=Rp.SubMatrix(1,3,3,3);
+   Real dot_zppo=zp(1)*po(1)+zp(2)*po(2)+zp(3)*po(3);
+   Real ao=M_PI_2-acos(dot_zppo/sqrt(zp.SumSquare()*po.SumSquare()));
+   Real r=(pl(1)*pl(1)+pl(2)*pl(2))/(pl(4)*pl(4));
+   Real tao=tan(ao);
+   tao*=tao;
+   Real tors=(r-pl(3)*pl(3)*tao)/(r+r*tao);
+   Real sign;
+   if(dot_zppo>0)
+      sign=(DotProduct(zp,pp)<0)?1:-1;
+   else
+      sign=(DotProduct(zp,pp)<0)?-1:1;
+   if(tors<0) {
+      //disp('out of reach')
+      converge=false;
+      return limit_angle(sign*M_PI_2,min,max);
+   } else {
+      Real to=sign*acos(sqrt(tors));
+      if(invert)
+         to=M_PI-to;
+      Real tl=atan2(pl(2),pl(1));
+      Real qtgt=normalize_angle(to-tl);
+      Real qans=limit_angle(qtgt,min,max);
+      converge=(qtgt==qans);
+      return qans;
+   }
+}
+
+Real Robot::computeThirdERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool invert, Real min, Real max, bool & converge) {
+   //We'll compute the knee angle first, using the
+   //  length of the thigh
+   //  distance from knee (curlink) to Plink
+   //  distance from shoulder (previous link) to Pobj
+   //use law of cosines to find angle at knee of Pobj and Plink, and the difference is the amount to move
+   Matrix Rp;
+   ColumnVector pp;
+   convertFrame(Rp,pp,curlink-1,curlink);
+   //cout << "Rp:\n" << Rp;
+   //cout << "pp:\n" << pp;
+   Real previous_to_cur_len=sqrt(pp(1)*pp(1)+pp(2)*pp(2));
+   //cout << "previous_to_cur_len==" << previous_to_cur_len <<endl;
+   ColumnVector pl=convertLink(endlink,curlink)*Plink;
+   //cout << "pl:\n" << pl;
+	 if(fabs(pl(1))<ITOL && fabs(pl(2))<ITOL) {
+		 //Plink is along axis of rotation - nothing we do is going to move it, so don't move at all
+		 converge=true; //debatable
+		 return links[curlink].get_q();
+	 }
+   Real tl=atan2(pl(2),pl(1));
+   Real tp=atan2(pp(2),pp(1));
+   //cout << "tl==" << tl << "  tp==" << tp << endl;
+   if(Plink(4)==0) {
+      //We're dealing with an infinite ray
+      //disp('out of reach (positive infinity)');
+		 Real qtgt=normalize_angle(tp-tl);
+		 Real qans=limit_angle(qtgt,min,max);
+		 converge=(qtgt==qans);
+		 return qans;
+   } else {
+      //Real cur_to_plink_xyz_len=homog_norm(pl);
+      Real plz=pl(3)/pl(4);
+      pl(3)=0;
+      //cout << "plz==" << plz << endl;
+      //cout << "pl:\n" << pl;
+      Real cur_to_plink_len=homog_norm(pl);
+      //cout << "cur_to_plink_len==" << cur_to_plink_len << endl;
+      ColumnVector prev_to_pobj=convertFrame(0,curlink-1)*Pobj;
+      //cout << "prev_to_pobj\n" << prev_to_pobj;
+      Real prev_to_pobj_xyz_len=homog_norm(prev_to_pobj);
+      //cout << "prev_to_pobj_xyz_len==" << prev_to_pobj_xyz_len << endl;
+      prev_to_pobj(3)=0;
+      //cout << "prev_to_pobj\n" << prev_to_pobj;
+			if(plz>prev_to_pobj_xyz_len) {
+				//Pobj is too close to center of rotation - fold up
+				converge=false;
+				return limit_angle(normalize_angle(tp-tl),min,max);
+			}
+			Real tgt_len=sqrt(prev_to_pobj_xyz_len*prev_to_pobj_xyz_len-plz*plz);
+			//cout << "tgt_len==" << tgt_len << endl;
+			Real aor_d=(2*cur_to_plink_len*previous_to_cur_len);
+			//cout << "aor_d==" << aor_d << endl;
+			//have to check if Pobj is within reach
+			if(abs(aor_d)<=ITOL) {
+				//Plink is along axis of rotation - nothing we do is going to move it, so don't move at all
+				//this should never be seen...
+				cout << "ASSERTION FAILED: " << __FILE__ << ':' << __LINE__ << endl;
+				converge=false;
+				return links[curlink].get_q();
+			} else {
+				Real aor=(cur_to_plink_len*cur_to_plink_len+previous_to_cur_len*previous_to_cur_len-tgt_len*tgt_len)/aor_d;
+				//cout << "aor=="<<aor<<endl;
+				if(aor<-1) { //Pobj is too far away - straighten out
+					//disp('out of reach (negative)');
+					converge=false;
+					return limit_angle(normalize_angle(M_PI+tp-tl),min,max);
+				} else if(aor>1) { //Pobj is too close to center of rotation - fold up
+					//disp('out of reach (positive)');
+					converge=false;
+					return limit_angle(normalize_angle(tp-tl),min,max);
+				} else {
+					Real ao=-acos(aor);
+					//cout << "ao=="<<ao<<endl;
+					if(invert)
+						ao=-ao;
+					//cout << "ao=="<<ao<<endl;
+					Real qtgt=normalize_angle(ao+tp-tl);
+					//cout << "qtgt=="<<qtgt<<endl;
+					Real qans=limit_angle(qtgt,min,max);
+					//cout << "qans=="<<qans<<endl;
+					converge=(qtgt==qans);
+					return qans;
+				}
+			}
+   }
+}
+
+
+
+// ----------------- M O D I F I E D  D H  N O T A T I O N ------------------
+
+
+ReturnMatrix mRobot::inv_kin(const Matrix & Tobj, const int mj)
+//!  @brief Overload inv_kin function.
+{
+   bool converge = false;
+   return inv_kin(Tobj, mj, dof, converge);
+}
+
+
+ReturnMatrix mRobot::inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Inverse kinematics solutions.
+
+  The solution is based on the analytic inverse kinematics if robot type (familly)
+  is Rhino or Puma, otherwise used the numerical algoritm defined in Robot_basic
+  class.
+*/
+{
+    switch (robotType) {
+	case RHINO:
+	    return inv_kin_rhino(Tobj, converge);
+	    break;
+	case PUMA:
+	    return inv_kin_puma(Tobj, converge);
+	    break;
+	default:
+	    return Robot_basic::inv_kin(Tobj, mj, endlink, converge);
+    }
+}
+
+
+ReturnMatrix mRobot::inv_kin_rhino(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Rhino inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(5), q_actual;    
+    q_actual = get_q();
+
+    try
+    {
+	Real theta[6] , diff1, diff2, tmp,
+	     angle , L=0.0 , M=0.0 , K=0.0 , H=0.0 , Gl=0.0 ;
+
+	if (links[6].d > 0)
+	{
+	    ColumnVector tmpd6(3); 
+	    tmpd6(1)=0; tmpd6(2)=0; tmpd6(3)=links[6].d;
+	    tmpd6 = Tobj.SubMatrix(1,3,1,3)*tmpd6;
+	    Tobj.SubMatrix(1,3,4,4) = Tobj.SubMatrix(1,3,4,4) - tmpd6;
+	}
+    
+	// Calcul les deux angles possibles
+	theta[0] = atan2(Tobj(2,4),
+			 Tobj(1,4));
+	
+	theta[1] = atan2(-Tobj(2,4),
+			 -Tobj(1,4))  ;
+	
+	diff1 = fabs(q_actual(1)-theta[0]) ;		
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)		   
+	    theta[1] = theta[0] ;
+	
+	theta[5] = atan2(sin(theta[1])*Tobj(1,1) - cos(theta[1])*Tobj(2,1), 
+			 sin(theta[1])*Tobj(1,2) - cos(theta[1])*Tobj(2,2));
+	
+	// angle = theta1 +theta2 + theta3
+	angle = atan2(-1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3),
+		      -1*Tobj(3,3));
+	
+	L = cos(theta[1])*Tobj(1,4) + 
+	    sin(theta[1])*Tobj(2,4) + 
+	    links[5].d*sin(angle) - 
+	    links[5].a*cos(angle);
+	M = links[1].d - 
+	    Tobj(3,4) - 
+	    links[5].d*cos(angle) - 
+	    links[5].a*sin(angle);
+	K = (L*L + M*M - links[4].a*links[4].a - 
+	     links[3].a*links[3].a) / 
+	    (2 * links[4].a * links[4].a);
+	
+	tmp = 1-K*K;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	theta[0] = atan2( sqrt(tmp) , K );
+	theta[3] = atan2( -sqrt(tmp) , K );	
+	
+	diff1 = fabs(q_actual(3)-theta[0]) ;
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	if (diff1 < diff2)
+	    theta[3] = theta[0] ;
+	
+	H = cos(theta[3]) * links[4].a + links[3].a;
+	Gl = sin(theta[3]) * links[4].a;
+	
+	theta[2] = atan2( M , L ) - atan2( Gl , H );
+	theta[4] = atan2( -1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3) , 
+			  -1*Tobj(3,3)) - theta[2] - theta[3] ;
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	set_q(qout);
+	
+	converge = true;
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+
+ReturnMatrix mRobot::inv_kin_puma(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Puma inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(6), q_actual;
+    q_actual = get_q();
+
+    try
+    {  
+	Real theta[7] , diff1, diff2, tmp,
+	     A = 0.0 , B = 0.0 , Cl = 0.0 , D =0.0, Ro = 0.0,
+	     H = 0.0 , L = 0.0 , M = 0.0;
+
+// Removed d6 component because in the Puma inverse kinematics solution 
+// d6 = 0. 
+	if (links[6].d)
+	{
+	    ColumnVector tmpd6(3);
+	    tmpd6(1)=0; tmpd6(2)=0; tmpd6(3)=links[6].d;
+	    tmpd6 = Tobj.SubMatrix(1,3,1,3)*tmpd6;
+	    Tobj.SubMatrix(1,3,4,4) = Tobj.SubMatrix(1,3,4,4) - tmpd6;
+	}
+	
+	tmp = Tobj(2,4)*Tobj(2,4) + Tobj(1,4)*Tobj(1,4);
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	Ro = sqrt(tmp);
+	D = (links[2].d+links[3].d) / Ro;
+	
+	tmp = 1-D*D;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	//Calcul les deux angles possibles
+	theta[0] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D, sqrt(tmp));	 
+	//Calcul les deux angles possibles
+	theta[1] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D , -sqrt(tmp));
+	
+	diff1 = fabs(q_actual(1)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[1] = theta[0];
+	
+	tmp = links[4].a*links[4].a + links[4].d*links[4].d;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	Ro = sqrt(tmp);
+	B = atan2(links[4].d,links[4].a);
+	Cl = Tobj(1,4)*Tobj(1,4) + 
+	     Tobj(2,4)*Tobj(2,4) + 
+	     Tobj(3,4)*Tobj(3,4) - 
+	     (links[2].d + links[3].d)*(links[2].d + links[3].d) - 
+	     links[3].a*links[3].a - 
+	     links[4].a*links[4].a - 
+	     links[4].d*links[4].d; 
+	A = Cl / (2*links[3].a);
+	
+	tmp = 1-A/Ro*A/Ro;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	theta[0] = atan2(sqrt(tmp) , A/Ro) + B;
+	theta[3] = atan2(-sqrt(tmp) , A/Ro) + B;
+	
+	diff1 = fabs(q_actual(3)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	//Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[3] = theta[0];
+	
+	H = cos(theta[1])*Tobj(1,4) + sin(theta[1])*Tobj(2,4);
+	L = sin(theta[3])*links[4].d + cos(theta[3])*links[4].a + links[3].a;
+	M = cos(theta[3])*links[4].d - sin(theta[3])*links[4].a;
+	
+	theta[2] = atan2( M , L ) - atan2(Tobj(3,4) , H );
+	
+	theta[0] = atan2( -sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3) , 
+			  cos(theta[2] + theta[3]) * 
+			  (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			  - (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[4] = atan2(-1*(-sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3)), 
+			 -cos(theta[2] + theta[3]) * 
+			 (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			 + (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	diff1 = fabs(q_actual(4)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(4)-theta[4]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[4] = theta[0];
+	
+	theta[5] = atan2( cos(theta[4]) * 
+			  ( cos(theta[2] + theta[3]) * 
+			    (cos(theta[1]) * Tobj(1,3) 
+			     + sin(theta[1])*Tobj(2,3)) 
+			    - (sin(theta[2]+theta[3])*Tobj(3,3)) ) + 
+			  sin(theta[4])*(-sin(theta[1])*Tobj(1,3) 
+					 + cos(theta[1])*Tobj(2,3)) , 
+			  sin(theta[2]+theta[3]) * (cos(theta[1]) * Tobj(1,3) 
+						    + sin(theta[1])*Tobj(2,3) ) 
+			  + (cos(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[6] = atan2( -sin(theta[4]) 
+			  * ( cos(theta[2] + theta[3]) * 
+			      (cos(theta[1]) * Tobj(1,1) 
+			       + sin(theta[1])*Tobj(2,1)) 
+			      - (sin(theta[2]+theta[3])*Tobj(3,1))) + 
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,1) 
+					 + cos(theta[1])*Tobj(2,1)), 
+			  -sin(theta[4]) * ( cos(theta[2] + theta[3]) * 
+					     (cos(theta[1]) * Tobj(1,2) 
+					      + sin(theta[1])*Tobj(2,2)) 
+					     - (sin(theta[2]+theta[3])*Tobj(3,2))) +
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,2) 
+					 + cos(theta[1])*Tobj(2,2)) );
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	qout(6) = theta[6];
+	set_q(qout);
+	
+	converge = true; 
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+
+ReturnMatrix mRobot_min_para::inv_kin(const Matrix & Tobj, const int mj)
+//!  @brief Overload inv_kin function.
+{
+   bool converge = false;
+   return inv_kin(Tobj, mj, dof, converge);
+}
+
+
+ReturnMatrix mRobot_min_para::inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+/*!
+  @brief Inverse kinematics solutions.
+
+  The solution is based on the analytic inverse kinematics if robot type (familly)
+  is Rhino or Puma, otherwise used the numerical algoritm defined in Robot_basic
+  class.
+*/
+{
+    switch (robotType) {
+	case RHINO:
+	    return inv_kin_rhino(Tobj, converge);
+	    break;
+	case PUMA:
+	    return inv_kin_puma(Tobj, converge);
+	    break;
+	default:
+	    return Robot_basic::inv_kin(Tobj, mj, endlink, converge);
+    }
+}
+
+
+ReturnMatrix mRobot_min_para::inv_kin_rhino(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Rhino inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(5), q_actual;    
+    q_actual = get_q();
+
+    try
+    {
+	Real theta[6] , diff1, diff2, tmp,
+	     angle , L=0.0 , M=0.0 , K=0.0 , H=0.0 , Gl=0.0 ;
+    
+	// Calcul les deux angles possibles
+	theta[0] = atan2(Tobj(2,4),
+			 Tobj(1,4));
+	
+	theta[1] = atan2(-Tobj(2,4),
+			 -Tobj(1,4))  ;
+	
+	diff1 = fabs(q_actual(1)-theta[0]) ;		
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)		   
+	    theta[1] = theta[0] ;
+	
+	theta[5] = atan2(sin(theta[1])*Tobj(1,1) - cos(theta[1])*Tobj(2,1), 
+			 sin(theta[1])*Tobj(1,2) - cos(theta[1])*Tobj(2,2));
+	
+	// angle = theta1 +theta2 + theta3
+	angle = atan2(-1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3),
+		      -1*Tobj(3,3));
+	
+	L = cos(theta[1])*Tobj(1,4) + 
+	    sin(theta[1])*Tobj(2,4) + 
+	    links[5].d*sin(angle) - 
+	    links[5].a*cos(angle);
+	M = links[1].d - 
+	    Tobj(3,4) - 
+	    links[5].d*cos(angle) - 
+	    links[5].a*sin(angle);
+	K = (L*L + M*M - links[4].a*links[4].a - 
+	     links[3].a*links[3].a) / 
+	    (2 * links[4].a * links[4].a);
+	
+	tmp = 1-K*K;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	theta[0] = atan2( sqrt(tmp) , K );
+	theta[3] = atan2( -sqrt(tmp) , K );	
+	
+	diff1 = fabs(q_actual(3)-theta[0]) ;
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2 ;
+	
+	if (diff1 < diff2)
+	    theta[3] = theta[0] ;
+	
+	H = cos(theta[3]) * links[4].a + links[3].a;
+	Gl = sin(theta[3]) * links[4].a;
+	
+	theta[2] = atan2( M , L ) - atan2( Gl , H );
+	theta[4] = atan2( -1*cos(theta[1])*Tobj(1,3) - sin(theta[1])*Tobj(2,3) , 
+			  -1*Tobj(3,3)) - theta[2] - theta[3] ;
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	set_q(qout);
+	
+	converge = true;
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+
+ReturnMatrix mRobot_min_para::inv_kin_puma(const Matrix & Tobj, bool & converge)
+/*!
+  @brief Analytic Puma inverse kinematics.
+
+  converge will be false if the desired end effector pose is outside robot range.
+*/
+{
+    ColumnVector qout(6), q_actual;
+    q_actual = get_q();
+
+    try
+    {  
+	Real theta[7] , diff1, diff2, tmp,
+	     A = 0.0 , B = 0.0 , Cl = 0.0 , D =0.0, Ro = 0.0,
+	     H = 0.0 , L = 0.0 , M = 0.0;
+
+// Removed d6 component because in the Puma inverse kinematics solution 
+// d6 = 0. 
+	if (links[6].d > 0)
+	{
+	    ColumnVector tmpd6(3);
+	    tmpd6(1)=0; tmpd6(2)=0; tmpd6(3)=links[6].d;
+	    tmpd6 = Tobj.SubMatrix(1,3,1,3)*tmpd6;
+	    Tobj.SubMatrix(1,3,4,4) = Tobj.SubMatrix(1,3,4,4) - tmpd6;
+	}
+	
+	tmp = Tobj(2,4)*Tobj(2,4) + Tobj(1,4)*Tobj(1,4);
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+
+	Ro = sqrt(tmp);
+	D = (links[2].d+links[3].d) / Ro;
+	
+	tmp = 1-D*D;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	//Calcul les deux angles possibles
+	theta[0] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D, sqrt(tmp));	 
+	//Calcul les deux angles possibles
+	theta[1] =  atan2(Tobj(2,4),Tobj(1,4)) - atan2(D , -sqrt(tmp));
+	
+	diff1 = fabs(q_actual(1)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(1)-theta[1]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[1] = theta[0];
+	
+	tmp = links[4].a*links[4].a + links[4].d*links[4].d;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	Ro = sqrt(tmp);
+	B = atan2(links[4].d,links[4].a);
+	Cl = Tobj(1,4)*Tobj(1,4) + 
+	     Tobj(2,4)*Tobj(2,4) + 
+	     Tobj(3,4)*Tobj(3,4) - 
+	     (links[2].d + links[3].d)*(links[2].d + links[3].d) - 
+	     links[3].a*links[3].a - 
+	     links[4].a*links[4].a - 
+	     links[4].d*links[4].d; 
+	A = Cl / (2*links[3].a);
+	
+	tmp = 1-A/Ro*A/Ro;
+	if (tmp < 0)
+	    throw std::out_of_range("sqrt of negative number not allowed.");
+	
+	theta[0] = atan2(sqrt(tmp) , A/Ro) + B;
+	theta[3] = atan2(-sqrt(tmp) , A/Ro) + B;
+	
+	diff1 = fabs(q_actual(3)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1 ;
+	
+	diff2 = fabs(q_actual(3)-theta[3]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	//Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[3] = theta[0];
+	
+	H = cos(theta[1])*Tobj(1,4) + sin(theta[1])*Tobj(2,4);
+	L = sin(theta[3])*links[4].d + cos(theta[3])*links[4].a + links[3].a;
+	M = cos(theta[3])*links[4].d - sin(theta[3])*links[4].a;
+	
+	theta[2] = atan2( M , L ) - atan2(Tobj(3,4) , H );
+	
+	theta[0] = atan2( -sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3) , 
+			  cos(theta[2] + theta[3]) * 
+			  (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			  - (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[4] = atan2(-1*(-sin(theta[1])*Tobj(1,3) + cos(theta[1])*Tobj(2,3)), 
+			 -cos(theta[2] + theta[3]) * 
+			 (cos(theta[1]) * Tobj(1,3) + sin(theta[1])*Tobj(2,3)) 
+			 + (sin(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	diff1 = fabs(q_actual(4)-theta[0]);
+	if (diff1 > M_PI)
+	    diff1 = 2*M_PI - diff1;
+	
+	diff2 = fabs(q_actual(4)-theta[4]);
+	if (diff2 > M_PI)
+	    diff1 = 2*M_PI - diff2;
+	
+	// Prend l'angle le plus proche de sa position actuel
+	if (diff1 < diff2)
+	    theta[4] = theta[0];
+	
+	theta[5] = atan2( cos(theta[4]) * 
+			  ( cos(theta[2] + theta[3]) * 
+			    (cos(theta[1]) * Tobj(1,3) 
+			     + sin(theta[1])*Tobj(2,3)) 
+			    - (sin(theta[2]+theta[3])*Tobj(3,3)) ) + 
+			  sin(theta[4])*(-sin(theta[1])*Tobj(1,3) 
+					 + cos(theta[1])*Tobj(2,3)) , 
+			  sin(theta[2]+theta[3]) * (cos(theta[1]) * Tobj(1,3) 
+						    + sin(theta[1])*Tobj(2,3) ) 
+			  + (cos(theta[2]+theta[3])*Tobj(3,3)) );
+	
+	theta[6] = atan2( -sin(theta[4]) 
+			  * ( cos(theta[2] + theta[3]) * 
+			      (cos(theta[1]) * Tobj(1,1) 
+			       + sin(theta[1])*Tobj(2,1)) 
+			      - (sin(theta[2]+theta[3])*Tobj(3,1))) + 
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,1) 
+					 + cos(theta[1])*Tobj(2,1)), 
+			  -sin(theta[4]) * ( cos(theta[2] + theta[3]) * 
+					     (cos(theta[1]) * Tobj(1,2) 
+					      + sin(theta[1])*Tobj(2,2)) 
+					     - (sin(theta[2]+theta[3])*Tobj(3,2))) +
+			  cos(theta[4])*(-sin(theta[1])*Tobj(1,2) 
+					 + cos(theta[1])*Tobj(2,2)) );
+	
+	qout(1) = theta[1];
+	qout(2) = theta[2];
+	qout(3) = theta[3];
+	qout(4) = theta[4];
+	qout(5) = theta[5];
+	qout(6) = theta[6];
+	set_q(qout);
+	
+	converge = true; 
+    }
+    catch(std::out_of_range & e)
+    {
+	converge = false; 
+	set_q(q_actual);
+	qout = q_actual;
+    }
+
+    qout.Release();
+    return qout;
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/kinemat.cpp
===================================================================
RCS file: Motion/roboop/kinemat.cpp
diff -N Motion/roboop/kinemat.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/kinemat.cpp	11 Oct 2004 22:01:28 -0000	1.15
@@ -0,0 +1,1225 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Rewrite mRobot::jacobian() since previous version was incorrect.
+   -Added functions kine_pd().
+   -Make sur that joint angles (qout) are in [-pi, pi] in inv_kin functions.
+
+2003/05/18: Etienne Lachance
+   -Added functions Robot_basic::jacobian_DLS_inv and 
+    Robot/mRobot/mRobot_min_para::jacobian_dot
+
+2003/08/22: Etienne Lachance
+   -Added parameter converge in inv_kin prototype function. It indicates if the
+    inverse kinematics solution converge.
+
+2003/11/26: Etienne Lachance
+   -Use angle conditions only if it converge in inv_kin.
+
+2004/01/23: Etienne Lachance
+   -Added const in non reference argument for all functions.
+
+2004/03/12: Etienne Lachance
+   -Added logic to set q in inv_kin. 
+
+2004/04/24: Etienne Lachance
+   -Moved inv_kin to invkine.cpp.
+
+2004/05/14: Etienne Lachance
+   -Replaced vec_x_prod by CrossProduct.
+
+2004/05/21: Etienne Lachance
+   -Added Doxygen comments.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/16: Ethan Tira-Thompson
+    -Supports Link::immobile flag so jacobians and deltas are 0 for immobile joints
+    -Jacobians will only contain entries for mobile joints - otherwise NaNs result
+     in later processing
+    -Added parameters to jacobian functions to generate for frames other than 
+     the end effector
+
+2004/07/21: Ethan Tira-Thompson
+    -Fixed a few bugs in previous modifications
+    -Added dTdqi(...,endlink) variants
+    -Renamed dp parameter of dTdqi to dpos so it doesn't shadow member variable
+
+2004/08/09: Ethan Tira-Thompson
+    -kine(0) will return the identity matrix instead of just an error
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file kinemat.cpp
+  @brief Kinematics functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: kinemat.cpp,v 1.15 2004/10/11 22:01:28 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+void Robot_basic::kine(Matrix & Rot, ColumnVector & pos)const
+/*!
+  @brief Direct kinematics at end effector.
+  @param Rot: End effector orientation.
+  @param pos: Enf effector position.
+*/
+{
+   kine(Rot,pos,dof+fix);
+}
+
+void Robot_basic::kine(Matrix & Rot, ColumnVector & pos, const int j)const
+/*!
+  @brief Direct kinematics at end effector.
+  @param Rot: Frame j orientation.
+  @param pos: Frame j position.
+  @param j: Selected frame.
+*/
+{
+   if(j < 0 || j > dof+fix) error("j must be 0 <= j <= dof+fix");
+   if(j == 0) {
+      Rot = R[0];
+      pos = p[0];
+      return;
+	 }
+
+   Rot = links[1].R;
+   pos = links[1].p;
+   for (int i = 2; i <= j; i++) {
+      pos = pos + Rot*links[i].p;
+      Rot = Rot*links[i].R;
+   }
+}
+
+ReturnMatrix Robot_basic::kine(void)const
+//! @brief Return the end effector direct kinematics transform matrix.
+{
+   Matrix thomo;
+
+   thomo = kine(dof+fix);
+   thomo.Release(); return thomo;
+}
+
+ReturnMatrix Robot_basic::kine(const int j)const
+//! @brief Return the frame j direct kinematics transform matrix.
+{
+   Matrix Rot, thomo(4,4);
+   ColumnVector pos;
+
+   kine(Rot,pos,j);
+   thomo << fourbyfourident;
+   thomo.SubMatrix(1,3,1,3) = Rot;
+   thomo.SubMatrix(1,3,4,4) = pos;
+   thomo.Release(); return thomo;
+}
+
+ReturnMatrix Robot_basic::kine_pd(const int j)const
+/*!
+  @brief Direct kinematics with velocity.
+
+  Return a \f$3\times 5\f$ matrix. The first three columns
+  are the frame j to the base rotation, the fourth column is
+  the frame j w.r.t to the base postion vector and the last 
+  column is the frame j w.r.t to the base translational 
+  velocity vector. Print an error on the console if j is
+  out of range.
+*/
+{
+   Matrix temp(3,5), Rot;
+   ColumnVector pos, pos_dot;
+
+   if(j < 1 || j > dof)
+     error("j must be 1 <= j <= dof");
+
+   kine_pd(Rot, pos, pos_dot, j);
+
+   temp.SubMatrix(1,3,1,3) = Rot;
+   temp.SubMatrix(1,3,4,4) = pos;
+   temp.SubMatrix(1,3,5,5) = pos_dot;
+   temp.Release();
+   return temp;
+}
+
+ReturnMatrix Robot_basic::jacobian_DLS_inv(const double eps, const double lambda_max,
+      const int ref)const
+/*!
+  @brief Inverse Jacobian based on damped least squares inverse.
+
+  @param eps: Range of singular region.
+  @param lambda_max: Value to obtain a good solution in singular region.
+  @param ref: Selected frame (ex: joint 4).
+
+  The Jacobian inverse, based on damped least squares, is 
+  \f[
+    J^{-1}(q) = \big(J^T(q)J(q) + \lambda^2I \big)^{-1}J^T(q)
+  \f]
+  where \f$\lambda\f$ and \f$I\f$ is a damping factor and the identity matrix 
+  respectively. Based on SVD (Singular Value Decomposition) the Jacobian is
+  \f$ J = \sum_{i=1}^{m}\sigma_i u_i v_i^T\f$, where \f$u_i\f$, \f$v_i\f$ and
+  \f$\sigma_i\f$ are respectively the input vector, the ouput vector and the
+  singular values (\f$\sigma_1 \geq \sigma_2 \cdots \geq \sigma_r \geq 0\f$, \f$r\f$
+  is the rank of J). Using the previous equations we obtain
+  \f[
+    J^{-1}(q) = \sum_{i=1}^{m} \frac{\sigma_i}{\sigma_i^2 + \lambda_i^2}v_iu_i
+  \f]
+  A singular region, based on the smallest singular value, can be defined by
+  \f[
+   \lambda^2 = \Bigg\{
+    \begin{array}{cc}
+      0 &     \textrm{si $\sigma_6 \geq \epsilon$} \\
+      \Big(1 - (\frac{\sigma_6}{\epsilon})^2 \Big)\lambda^2_{max} & \textrm{sinon}
+    \end{array}
+  \f] 
+*/
+{
+   Matrix jacob_inv_DLS, U, V;
+   DiagonalMatrix Q;
+   SVD(jacobian(ref), Q, U, V);
+
+   if(Q(6,6) >= eps)
+      jacob_inv_DLS = V*Q.i()*U.t();
+   else
+   {
+      Q(6,6) += (1 - pow(Q(6,6)/eps,2))*lambda_max*lambda_max;
+      jacob_inv_DLS = V*Q.i()*U.t();
+   }
+
+   jacob_inv_DLS.Release();
+   return(jacob_inv_DLS);
+}
+
+/*! @brief converts one or more column-wise vectors from frame @a cur to frame @a dest
+ *  @param[out] R on return contains rotation matrix between @a cur and @a dest
+ *  @param[out] p on return contains vector from @a cur to @a dest
+ *  @param[in] cur is the current frame
+ *  @param[in] dest is the target frame */
+void Robot_basic::convertFrame(Matrix& R, ColumnVector& p, int cur, int dest) const {
+   if(cur>dest && cur>0) {
+     if(dest<=0)
+        dest=1; //skip identity matrix
+     R=links[dest].R;
+     p=links[dest].p;
+     for(dest++;dest<cur;dest++) {
+       p=p+R*links[dest].p;
+       R=R*links[dest].R;
+     }
+   } else if(cur<dest && dest>0) {
+     if(cur<=0)
+        cur=1; //skip identity matrix
+     R=links[cur].R;
+     p=links[cur].p;
+     for(cur++;cur<dest;cur++) {
+       p=p+R*links[cur].p;
+       R=R*links[cur].R;
+     }
+     R=R.t();
+     p=R*-p;
+   } else {
+      R=Matrix(3,3);
+      R<<threebythreeident;
+      p=ColumnVector(3);
+      p=0;
+   }
+}
+/*! @brief Returns a matrix which can be used to convert from frame @a cur to frame @a dest
+ *  The Matrix returned will be homogenous (4x4). */
+ReturnMatrix Robot_basic::convertFrame(int cur, int dest) const {
+   Matrix R;
+   ColumnVector p;
+   convertFrame(R,p,cur,dest);
+   return pack4x4(R,p);
+}
+
+/*! @brief converts vector(s) on link @a cur to be vector(s) on link @a dest
+ *  @param[out] R on return contains rotation matrix between @a cur and @a dest
+ *  @param[out] p on return contains vector from @a cur to @a dest
+ *  @param[in] cur the link vectors of @a A are currently relative to
+ *  @param[in] dest the link vectors should be converted to
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will match the homogenousness of @a A. */
+void Robot_basic::convertLinkToFrame(Matrix& R, ColumnVector& p, int cur, int dest) const {
+   convertFrame(R,p,cur,dest);
+   if(cur<1)
+      return;
+   if(links[cur].get_joint_type()==0) {
+      Matrix rotz3(3,3);
+      rotz3 << threebythreeident;
+      rotz3(1,1)=rotz3(2,2)=cos((links[cur].get_theta()-links[cur].get_joint_offset()));
+      rotz3(1,2)=-(rotz3(2,1)=sin((links[cur].get_theta()-links[cur].get_joint_offset())));
+      R*=rotz3;
+   } else {
+      p+=R.SubMatrix(1,3,3,3)*((links[cur].get_d()-links[cur].get_joint_offset()));
+   }
+}
+
+/*! @brief Returns a matrix which can be used to convert from link @a cur to frame @a dest
+ *  @param cur the source link
+ *  @param dest the target frame
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will be homogenous (4x4). */
+ReturnMatrix Robot_basic::convertLinkToFrame(int cur, int dest) const {
+   Matrix R;
+   ColumnVector p;
+   convertLinkToFrame(R,p,cur,dest);
+   return pack4x4(R,p);
+}
+
+/*! @brief converts vector(s) on link @a cur to be vector(s) on link @a dest
+ *  @param[out] R on return contains rotation matrix between @a cur and @a dest
+ *  @param[out] p on return contains vector from @a cur to @a dest
+ *  @param[in] cur the link vectors of @a A are currently relative to
+ *  @param[in] dest the link vectors should be converted to
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will match the homogenousness of @a A. */
+void Robot_basic::convertFrameToLink(Matrix& R, ColumnVector& p, int cur, int dest) const {
+   convertFrame(R,p,cur,dest);
+   if(dest<1)
+      return;
+   if(links[dest].get_joint_type()==0) {
+      Matrix rotz3(3,3);
+      rotz3 << threebythreeident;
+      rotz3(1,1)=rotz3(2,2)=cos(-(links[dest].get_theta()-links[dest].get_joint_offset()));
+      rotz3(1,2)=-(rotz3(2,1)=sin(-(links[dest].get_theta()-links[dest].get_joint_offset())));
+      R=rotz3*R;
+      p=rotz3*p;
+   } else {
+      p(3)+=-(links[dest].get_d()-links[dest].get_joint_offset());
+   }
+}
+
+/*! @brief Returns a matrix which can be used to convert from link @a cur to link @a dest
+ *  @param cur the source link
+ *  @param dest the target link
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will be homogenous (4x4). */
+ReturnMatrix Robot_basic::convertFrameToLink(int cur, int dest) const {
+   Matrix R;
+   ColumnVector p;
+   convertFrameToLink(R,p,cur,dest);
+	 return pack4x4(R,p);
+}
+
+/*! @brief converts vector(s) on link @a cur to be vector(s) on link @a dest
+ *  @param[out] R on return contains rotation matrix between @a cur and @a dest
+ *  @param[out] p on return contains vector from @a cur to @a dest
+ *  @param[in] cur the link vectors of @a A are currently relative to
+ *  @param[in] dest the link vectors should be converted to
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will match the homogenousness of @a A. */
+void Robot_basic::convertLink(Matrix& R, ColumnVector& p, int cur, int dest) const {
+   convertFrame(R,p,cur,dest);
+   if(cur>0) {
+      if(links[cur].get_joint_type()==0) {
+         Matrix rotz3(3,3);
+         rotz3 << threebythreeident;
+         rotz3(1,1)=rotz3(2,2)=cos((links[cur].get_theta()-links[cur].get_joint_offset()));
+         rotz3(1,2)=-(rotz3(2,1)=sin((links[cur].get_theta()-links[cur].get_joint_offset())));
+         R*=rotz3;
+      } else {
+         p+=R.SubMatrix(1,3,3,3)*((links[cur].get_d()-links[cur].get_joint_offset()));
+      }
+   }
+   if(dest<1)
+      return;
+   if(links[dest].get_joint_type()==0) {
+      Matrix rotz3(3,3);
+      rotz3 << threebythreeident;
+      rotz3(1,1)=rotz3(2,2)=cos(-(links[dest].get_theta()-links[dest].get_joint_offset()));
+      rotz3(1,2)=-(rotz3(2,1)=sin(-(links[dest].get_theta()-links[dest].get_joint_offset())));
+      R=rotz3*R;
+      p=rotz3*p;
+   } else {
+      p(3)+=-(links[dest].get_d()-links[dest].get_joint_offset());
+   }
+}
+
+/*! @brief Returns a matrix which can be used to convert from link @a cur to link @a dest
+ *  @param cur the source link
+ *  @param dest the target link
+ *
+ *  Note the difference between this and convertFrame is that a link
+ *  moves within the frame at its joints origin - the frame is static
+ *  no matter how the joint moves within it.  If we have a point on
+ *  the link, then the position of that point will move within the frame
+ *  as the joint moves.  This function will return vector(s) of A
+ *  represented as if they were connected to link @a dest.\n
+ *  The Matrix returned will be homogenous (4x4). */
+ReturnMatrix Robot_basic::convertLink(int cur, int dest) const {
+   Matrix R;
+   ColumnVector p;
+   convertLink(R,p,cur,dest);
+   return pack4x4(R,p);
+}
+
+
+// ---------------------  R O B O T   DH   N O T A T I O N  --------------------------
+
+void Robot::kine_pd(Matrix & Rot, ColumnVector & pos, ColumnVector & pos_dot,
+                    const int j)const
+/*!
+  @brief Direct kinematics with velocity.
+  @param Rot: Frame j rotation matrix w.r.t to the base frame.
+  @param pos: Frame j position vector wr.r.t to the base frame.
+  @param pos_dot: Frame j velocity vector w.r.t to the base frame.
+  @param j: Frame j.
+  Print an error on the console if j is out of range.
+*/
+{
+   if(j < 1 || j > dof)
+      error("j must be 1 <= j <= dof");
+
+   if( (pos.Nrows()!=3) || (pos.Ncols()!=1) )
+       pos = ColumnVector(3); 
+   if( (pos_dot.Nrows()!=3) || (pos_dot.Ncols()!=1) )
+     pos_dot = ColumnVector(3);
+
+   pos = 0.0;
+   pos_dot = 0.0;
+   for(int i = 1; i <= j; i++)
+   {
+      R[i] = R[i-1]*links[i].R;
+      pos = pos + R[i-1]*links[i].p;
+      pos_dot = pos_dot + CrossProduct(R[i]*w[i], R[i-1]*links[i].p);
+   }
+   Rot = R[j];
+}
+
+void Robot::dTdqi(Matrix & dRot, ColumnVector & dpos,
+                  const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  This function computes the partial derivatives:
+  \f[
+  \frac{\partial{}^0 T_n}{\partial q_i} = {}^0 T_{i-1} Q_i \; {}^{i-1} T_n
+  \f]
+  in standard notation and
+  \f[
+
+  \frac{\partial{}^0 T_n}{\partial q_i} = {}^0 T_{i} Q_i \; {}^{i} T_n
+  \f]
+  in modified notation,
+
+ with
+ \f[
+ Q_i = 
+  \left [
+    \begin{array}{cccc}
+      0 & -1 & 0 & 0 \\
+      1 & 0 & 0 & 0 \\
+      0 & 0 & 0 & 0 \\
+      0 & 0 & 0 & 0
+    \end{array}
+  \right ]
+  \f]
+ for a revolute joint and
+ \f[
+  Q_i = 
+  \left [
+   \begin{array}{cccc}
+     0 & 0 & 0 & 0 \\
+     0 & 0 & 0 & 0 \\
+     0 & 0 & 0 & 1 \\
+     0 & 0 & 0 & 0
+   \end{array}
+  \right ]
+  \f]
+  for a prismatic joint.
+
+  \f$dRot\f$ and \f$dp\f$ are modified on output.
+*/
+{
+   int j;
+   if(i < 1 || i > endlink) error("i must be 1 <= i <= endlink");
+   if(links[i].get_immobile()) {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+   } else if(links[i].get_joint_type() == 0) {
+      Matrix dR(3,3);
+      dR = 0.0;
+      Matrix R2 = links[i].R;
+      ColumnVector p2 = links[i].p;
+      dRot = Matrix(3,3);
+      dRot << threebythreeident;
+      for(j = 1; j < i; j++) {
+         dRot = dRot*links[j].R;
+      }
+      // dRot * Q
+      for(j = 1; j <= 3; j++) {
+         dR(j,1) = dRot(j,2);
+         dR(j,2) = -dRot(j,1);
+      }
+      for(j = i+1; j <= endlink; j++) {
+         p2 = p2 + R2*links[j].p;
+         R2 = R2*links[j].R;
+      }
+      dpos = dR*p2;
+      dRot = dR*R2;
+   } else {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+      dpos(3) = 1.0;
+      for(j = i-1; j >= 1; j--) {
+         dpos = links[j].R*dpos;
+      }
+   }
+}
+
+ReturnMatrix Robot::dTdqi(const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  See Robot::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+  for equations.
+*/
+{
+   Matrix dRot, thomo(4,4);
+   ColumnVector dpos;
+
+   dTdqi(dRot, dpos, i, endlink);
+   thomo = (Real) 0.0;
+   thomo.SubMatrix(1,3,1,3) = dRot;
+   thomo.SubMatrix(1,3,4,4) = dpos;
+   thomo.Release(); return thomo;
+}
+
+ReturnMatrix Robot::jacobian(const int endlink, const int ref)const
+/*!
+  @brief Jacobian of mobile links up to endlink expressed at frame ref.
+
+  The Jacobian expressed in based frame is
+  \f[
+    ^{0}J(q) = 
+    \left[ 
+     \begin{array}{cccc}
+      ^{0}J_1(q) & ^{0}J_2(q) & \cdots & ^{0}J_n(q) \\
+     \end{array} 
+   \right]
+  \f]
+  where \f$^{0}J_i(q)\f$ is defined by
+  \f[
+    ^{0}J_i(q) = 
+     \begin{array}{cc}
+      \left[ 
+       \begin{array}{c}
+        z_i \times ^{i}p_n \\
+        z_i \\
+       \end{array} 
+      \right] & \textrm{rotoid joint} 
+     \end{array} 
+   \f]
+   \f[
+    ^{0}J_i(q) = 
+      \begin{array}{cc}
+       \left[ 
+        \begin{array}{c}
+         z_i \\
+         0 \\
+        \end{array} 
+       \right] & \textrm{prismatic joint} \\
+      \end{array}
+  \f]
+
+  Expressed in a different frame the Jacobian is obtained by
+  \f[
+    ^{i}J(q)  = 
+    \left[
+     \begin{array}{cc}
+      ^{0}_iR^T & 0 \\
+        0 & ^{0}_iR^T
+     \end{array} 
+    \right] 
+   {^{0}}J(q)
+  \f]
+*/
+{
+   const int adof=get_available_dof(endlink);
+   Matrix jac(6,adof);
+   Matrix pr, temp(3,1);
+
+   if(ref < 0 || ref > dof) error("invalid referential");
+
+   for(int i = 1; i <= dof; i++) {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1]+R[i-1]*links[i].p;
+   }
+
+   for(int i=1,j=1; j <= adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0) {
+         temp(1,1) = R[i-1](1,3);
+         temp(2,1) = R[i-1](2,3);
+         temp(3,1) = R[i-1](3,3);
+         pr = p[endlink]-p[i-1];
+         temp = CrossProduct(temp,pr);
+         jac(1,j) = temp(1,1);
+         jac(2,j) = temp(2,1);
+         jac(3,j) = temp(3,1);
+         jac(4,j) = R[i-1](1,3);
+         jac(5,j) = R[i-1](2,3);
+         jac(6,j) = R[i-1](3,3);
+      } else {
+         jac(1,j) = R[i-1](1,3);
+         jac(2,j) = R[i-1](2,3);
+         jac(3,j) = R[i-1](3,3);
+         jac(4,j) = jac(5,j) = jac(6,j) = 0.0;
+      }
+      j++;
+   }
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jac = Rot*jac;
+   }
+
+   jac.Release(); return jac;
+}
+
+ReturnMatrix Robot::jacobian_dot(const int ref)const
+/*!
+  @brief Jacobian derivative of mobile joints expressed at frame ref.
+
+  The Jacobian derivative expressed in based frame is
+  \f[
+   ^{0}\dot{J}(q,\dot{q}) = 
+    \left[ 
+     \begin{array}{cccc}
+       ^{0}\dot{J}_1(q,\dot{q}) & ^{0}\dot{J}_2(q,\dot{q}) & \cdots & ^{0}\dot{J}_n(q,\dot{q}) \\
+     \end{array} 
+    \right]
+  \f]
+  where \f$^{0}\dot{J}_i(q,\dot{q})\f$ is defined by
+  \f[
+   ^{0}\dot{J}_i(q,\dot{q}) = 
+    \begin{array}{cc}
+     \left[ 
+      \begin{array}{c}
+       \omega_{i-1} \times z_i \\
+       \omega_{i-1} \times ^{i-1}p_n + z_i \times ^{i-1}\dot{p}_n
+     \end{array} 
+    \right] & \textrm{rotoid joint} 
+   \end{array}
+  \f]
+  \f[
+   ^{0}\dot{J}_i(q,\dot{q}) =
+   \begin{array}{cc}
+    \left[ 
+     \begin{array}{c}
+       0 \\
+       0 \\
+     \end{array} 
+    \right] & \textrm{prismatic joint} \\
+   \end{array}
+  \f]
+  Expressed in a different frame the Jacobian derivative is obtained by
+  \f[
+    ^{i}J(q)  = 
+    \left[
+     \begin{array}{cc}
+      ^{0}_iR^T & 0 \\
+        0 & ^{0}_iR^T
+     \end{array} 
+    \right] 
+   {^{0}}J(q)
+  \f]
+*/
+{
+   const int adof=get_available_dof();
+   Matrix jacdot(6,adof);
+   ColumnVector e(3), temp, pr, ppr;
+
+   if(ref < 0 || ref > dof)
+      error("invalid referential");
+
+   for(int i = 1; i <= dof; i++)
+   {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1] + R[i-1]*links[i].p;
+      pp[i] = pp[i-1] + CrossProduct(R[i]*w[i], R[i-1]*links[i].p);
+   }
+
+   for(int i=1,j=1; j <= adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0)
+      {
+         pr = p[dof]-p[i-1];
+         ppr = pp[dof]-pp[i-1];
+         e(1) = R[i-1](1,3);
+         e(2) = R[i-1](2,3);
+         e(3) = R[i-1](3,3);
+         temp = CrossProduct(R[i-1]*w[i-1], e);
+         jacdot(4,j) = temp(1);           // d(e)/dt
+         jacdot(5,j) = temp(2);
+         jacdot(6,j) = temp(3);
+         temp = CrossProduct(temp,pr) + CrossProduct(e,ppr);
+         jacdot(1,j) = temp(1);
+         jacdot(2,j) = temp(2);
+         jacdot(3,j) = temp(3);
+      }
+      else
+         jacdot(1,j) = jacdot(2,j) = jacdot(3,j) =
+            jacdot(4,j) = jacdot(5,j) = jacdot(6,j) = 0.0;
+      j++;
+   }
+
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jacdot = Rot*jacdot;
+   }
+
+   jacdot.Release(); return jacdot;
+}
+
+// ----------------  R O B O T   M O D I F I E D   DH   N O T A T I O N  --------------------------
+
+void mRobot::kine_pd(Matrix & Rot, ColumnVector & pos, ColumnVector & pos_dot,
+                     const int j)const
+/*!
+  @brief Direct kinematics with velocity.
+  @param Rot: Frame j rotation matrix w.r.t to the base frame.
+  @param pos: Frame j position vector wr.r.t to the base frame.
+  @param pos_dot: Frame j velocity vector w.r.t to the base frame.
+  @param j: Frame j.
+  Print an error on the console if j is out of range.
+*/
+{
+   if(j < 1 || j > dof+fix)
+      error("j must be 1 <= j <= dof+fix");
+
+   if( (pos.Nrows()!=3) || (pos.Ncols()!=1) )
+       pos = ColumnVector(3); 
+   if( (pos_dot.Nrows()!=3) || (pos_dot.Ncols()!=1) )
+     pos_dot = ColumnVector(3);
+
+   pos = 0.0;
+   pos_dot = 0.0;
+   for(int i = 1; i <= j; i++)
+   {
+      pos = pos + R[i-1]*links[i].p;
+      pos_dot = pos_dot + R[i-1]*CrossProduct(w[i-1], links[i].p);
+      R[i] = R[i-1]*links[i].R;
+   }
+   Rot = R[j];
+}
+
+void mRobot::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  This function computes the partial derivatives:
+  \f[
+  \frac{\partial{}^0 T_n}{\partial q_i} = {}^0 T_{i} Q_i \; {}^{i} T_n
+  \f]
+  with
+  \f[
+  Q_i = 
+  \left [
+    \begin{array}{cccc}
+      0 & -1 & 0 & 0 \\
+      1 & 0 & 0 & 0 \\
+      0 & 0 & 0 & 0 \\
+      0 & 0 & 0 & 0
+    \end{array}
+  \right ]
+  \f]
+ for a revolute joint and
+ \f[
+  Q_i = 
+  \left [
+   \begin{array}{cccc}
+     0 & 0 & 0 & 0 \\
+     0 & 0 & 0 & 0 \\
+     0 & 0 & 0 & 1 \\
+     0 & 0 & 0 & 0
+   \end{array}
+  \right ]
+  \f]
+  for a prismatic joint.
+
+  \f$dRot\f$ and \f$dp\f$ are modified on output.
+*/
+{
+   int j;
+   if(i < 1 || i > endlink) error("i must be 1 <= i <= endlink");
+   if(links[i].get_immobile()) {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+   } else if(links[i].get_joint_type() == 0) {
+      Matrix dR(3,3), R2(3,3), p2(3,1);
+      dR = 0.0;
+      dRot = Matrix(3,3);
+      dRot << threebythreeident;
+      for(j = 1; j <= i; j++) {
+         dRot = dRot*links[j].R;
+      }
+      // dRot * Q
+      for(j = 1; j <= 3; j++) {
+         dR(j,1) = dRot(j,2);
+         dR(j,2) = -dRot(j,1);
+      }
+      if(i < endlink) {
+         R2 = links[i+1].R;
+         p2 = links[i+1].p;
+      } else {
+         R2 <<  threebythreeident;
+         p2 = 0.0;
+      }
+      for(j = i+1; j <= endlink; j++) {
+         p2 = p2 + R2*links[j].p;
+         R2 = R2*links[j].R;
+      }
+      dpos = dR*p2;
+      dRot = dR*R2;  // probleme ...
+   } else {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+      dpos(3) = 1.0;
+      for(j = i; j >= 1; j--) {
+         dpos = links[j].R*dpos;
+      }
+   }
+}
+
+ReturnMatrix mRobot::dTdqi(const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  See mRobot::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+  for equations.
+*/
+{
+   Matrix dRot, thomo(4,4);
+   ColumnVector dpos;
+
+   dTdqi(dRot, dpos, i, endlink);
+   thomo = (Real) 0.0;
+   thomo.SubMatrix(1,3,1,3) = dRot;
+   thomo.SubMatrix(1,3,4,4) = dpos;
+   thomo.Release(); return thomo;
+}
+
+ReturnMatrix mRobot::jacobian(const int endlink, const int ref)const
+/*!
+  @brief Jacobian of mobile joints up to endlink expressed at frame ref.
+
+  See Robot::jacobian for equations.
+*/
+{
+   const int adof=get_available_dof(endlink);
+   Matrix jac(6,adof);
+   ColumnVector pr(3), temp(3);
+
+   if(ref < 0 || ref > dof+fix)
+      error("invalid referential");
+
+   for(int i = 1; i <= dof+fix; i++) {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1] + R[i-1]*links[i].p;
+   }
+
+   for(int i=1,j=1; j <= adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0){
+         temp(1) = R[i](1,3);
+         temp(2) = R[i](2,3);
+         temp(3) = R[i](3,3);
+         pr = p[endlink+fix]-p[i];
+         temp = CrossProduct(temp,pr);
+         jac(1,j) = temp(1);
+         jac(2,j) = temp(2);
+         jac(3,j) = temp(3);
+         jac(4,j) = R[i](1,3);
+         jac(5,j) = R[i](2,3);
+         jac(6,j) = R[i](3,3);
+      } else {
+         jac(1,j) = R[i](1,3);
+         jac(2,j) = R[i](2,3);
+         jac(3,j) = R[i](3,3);
+         jac(4,j) = jac(5,j) = jac(6,j) = 0.0;
+      }
+      j++;
+   }
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jac = Rot*jac;
+   }
+   jac.Release(); return jac;
+}
+
+ReturnMatrix mRobot::jacobian_dot(const int ref)const
+/*!
+  @brief Jacobian derivative of mobile joints expressed at frame ref.
+
+  See Robot::jacobian_dot for equations.
+*/
+{
+   const int adof=get_available_dof();
+   Matrix jacdot(6,adof);
+   ColumnVector e(3), temp, pr, ppr;
+
+   if(ref < 0 || ref > dof+fix)
+      error("invalid referential");
+
+   for(int i = 1; i <= dof+fix; i++)
+   {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1] + R[i-1]*links[i].p;
+      pp[i] = pp[i-1] + R[i-1]*CrossProduct(w[i-1], links[i].p);
+   }
+
+   for(int i=1,j=1; j <= adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0)
+      {
+         pr = p[dof+fix]-p[i];
+         ppr = pp[dof+fix]-pp[i];
+
+         e(1) = R[i](1,3);
+         e(2) = R[i](2,3);
+         e(3) = R[i](3,3);
+         temp = CrossProduct(R[i-1]*w[i-1], e);
+         jacdot(4,j) = temp(1);           // d(e)/dt
+         jacdot(5,j) = temp(2);
+         jacdot(6,j) = temp(3);
+
+         temp = CrossProduct(temp,pr) + CrossProduct(e,ppr);
+         jacdot(1,j) = temp(1);
+         jacdot(2,j) = temp(2);
+         jacdot(3,j) = temp(3);
+      }
+      else
+         jacdot(1,j) = jacdot(2,j) = jacdot(3,j) =
+            jacdot(4,j) = jacdot(5,j) = jacdot(6,j) = 0.0;
+      j++;
+   }
+
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jacdot = Rot*jacdot;
+   }
+
+   jacdot.Release(); return jacdot;
+}
+
+// ------------- R O B O T  DH  M O D I F I E D,  M I N I M U M   P A R A M E T E R S  ------------
+
+void mRobot_min_para::kine_pd(Matrix & Rot, ColumnVector & pos, ColumnVector & pos_dot,
+                              const int j)const
+/*!
+  @brief Direct kinematics with velocity.
+  @param Rot: Frame j rotation matrix w.r.t to the base frame.
+  @param pos: Frame j position vector wr.r.t to the base frame.
+  @param pos_dot: Frame j velocity vector w.r.t to the base frame.
+  @param j: Frame j.
+  Print an error on the console if j is out of range.
+*/
+{
+   if(j < 1 || j > dof+fix)
+      error("j must be 1 <= j <= dof+fix");
+
+   if( (pos.Nrows()!=3) || (pos.Ncols()!=1) )
+       pos = ColumnVector(3); 
+   if( (pos_dot.Nrows()!=3) || (pos_dot.Ncols()!=1) )
+     pos_dot = ColumnVector(3);
+
+   pos = 0.0;
+   pos_dot = 0.0;
+   for(int i = 1; i <= j; i++)
+   {
+      pos = pos + R[i-1]*links[i].p;
+      pos_dot = pos_dot + R[i-1]*CrossProduct(w[i-1], links[i].p);
+      R[i] = R[i-1]*links[i].R;
+   }
+   Rot = R[j];
+}
+
+void mRobot_min_para::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  This function computes the partial derivatives:
+  \f[
+  \frac{\partial{}^0 T_n}{\partial q_i} = {}^0 T_{i} Q_i \; {}^{i} T_n
+  \f]
+
+  See mRobot::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+  for equations.
+*/
+{
+   int j;
+   if(i < 1 || i > endlink) error("i must be 1 <= i <= endlink");
+   if(links[i].get_immobile()) {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+   } else if(links[i].get_joint_type() == 0) {
+      Matrix dR(3,3), R2, p2(3,1);
+      dR = 0.0;
+      dRot = Matrix(3,3);
+      dRot << threebythreeident;
+      for(j = 1; j <= i; j++) {
+         dRot = dRot*links[j].R;
+      }
+      // dRot * Q
+      for(j = 1; j <= 3; j++) {
+         dR(j,1) = dRot(j,2);
+         dR(j,2) = -dRot(j,1);
+      }
+      if(i < endlink) {
+         R2 = links[i+1].R;
+         p2 = links[i+1].p;
+      } else {
+         R2 <<  threebythreeident;
+         p2 = 0.0;
+      }
+      for(j = i+1; j <= endlink; j++) {
+         p2 = p2 + R2*links[j].p;
+         R2 = R2*links[j].R;
+      }
+      dpos = dR*p2;
+      dRot = dR*R2;
+   } else {
+      dRot = Matrix(3,3);
+      dpos = Matrix(3,1);
+      dRot = 0.0;
+      dpos = 0.0;
+      dpos(3) = 1.0;
+      for(j = i; j >= 1; j--) {
+         dpos = links[j].R*dpos;
+      }
+   }
+}
+
+ReturnMatrix mRobot_min_para::dTdqi(const int i, const int endlink)
+/*!
+  @brief Partial derivative of the robot position (homogeneous transf.)
+
+  See mRobot::dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+  for equations.
+*/
+{
+   Matrix dRot, thomo(4,4);
+   ColumnVector dpos;
+
+   dTdqi(dRot, dpos, i, endlink);
+   thomo = (Real) 0.0;
+   thomo.SubMatrix(1,3,1,3) = dRot;
+   thomo.SubMatrix(1,3,4,4) = dpos;
+   thomo.Release(); return thomo;
+}
+
+ReturnMatrix mRobot_min_para::jacobian(const int endlink, const int ref)const
+/*!
+  @brief Jacobian of mobile joints up to endlink expressed at frame ref.
+
+  See Robot::jacobian for equations.
+*/
+{
+   const int adof=get_available_dof(endlink);
+   Matrix jac(6,adof);
+   ColumnVector pr(3), temp(3);
+
+   if(ref < 0 || ref > dof+fix)
+      error("invalid referential");
+
+   for(int i = 1; i <= dof+fix; i++) {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1] + R[i-1]*links[i].p;
+   }
+
+   for(int i=1,j=1; j<=adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0){
+         temp(1) = R[i](1,3);
+         temp(2) = R[i](2,3);
+         temp(3) = R[i](3,3);
+
+         pr = p[endlink+fix]-p[i];
+         temp = CrossProduct(temp,pr);
+         jac(1,j) = temp(1);
+         jac(2,j) = temp(2);
+         jac(3,j) = temp(3);
+         jac(4,j) = R[i](1,3);
+         jac(5,j) = R[i](2,3);
+         jac(6,j) = R[i](3,3);
+      } else {
+         jac(1,j) = R[i](1,3);
+         jac(2,j) = R[i](2,3);
+         jac(3,j) = R[i](3,3);
+         jac(4,j) = jac(5,j) = jac(6,j) = 0.0;
+      }
+      j++;
+   }
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jac = Rot*jac;
+   }
+
+   jac.Release(); return jac;
+}
+
+ReturnMatrix mRobot_min_para::jacobian_dot(const int ref)const
+/*!
+  @brief Jacobian derivative of mobile joints expressed at frame ref.
+
+  See Robot::jacobian_dot for equations.
+*/
+{
+   const int adof=get_available_dof();
+   Matrix jacdot(6,adof);
+   ColumnVector e(3), temp, pr, ppr;
+
+   if(ref < 0 || ref > dof+fix)
+      error("invalid referential");
+
+   for(int i = 1; i <= dof+fix; i++)
+   {
+      R[i] = R[i-1]*links[i].R;
+      p[i] = p[i-1] + R[i-1]*links[i].p;
+      pp[i] = pp[i-1] + R[i-1]*CrossProduct(w[i-1], links[i].p);
+   }
+
+   for(int i=1,j=1; j <= adof; i++) {
+      if(links[i].get_immobile())
+         continue;
+      if(links[i].get_joint_type() == 0)
+      {
+         pr = p[dof+fix]-p[i];
+         ppr = pp[dof+fix]-pp[i];
+
+         e(1) = R[i](1,3);
+         e(2) = R[i](2,3);
+         e(3) = R[i](3,3);
+         temp = CrossProduct(R[i-1]*w[i-1], e);
+         jacdot(4,j) = temp(1);           // d(e)/dt
+         jacdot(5,j) = temp(2);
+         jacdot(6,j) = temp(3);
+
+         temp = CrossProduct(temp,pr) + CrossProduct(e,ppr);
+         jacdot(1,j) = temp(1);
+         jacdot(2,j) = temp(2);
+         jacdot(3,j) = temp(3);
+      }
+      else
+         jacdot(1,j) = jacdot(2,j) = jacdot(3,j) =
+            jacdot(4,j) = jacdot(5,j) = jacdot(6,j) = 0.0;
+      j++;
+   }
+
+   if(ref != 0) {
+      Matrix zeros(3,3);
+      zeros = (Real) 0.0;
+      Matrix RT = R[ref].t();
+      Matrix Rot;
+      Rot = ((RT & zeros) | (zeros & RT));
+      jacdot = Rot*jacdot;
+   }
+
+   jacdot.Release(); return jacdot;
+}
+
+#ifdef use_namespace
+}
+#endif
Index: Motion/roboop/quaternion.cpp
===================================================================
RCS file: Motion/roboop/quaternion.cpp
diff -N Motion/roboop/quaternion.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/quaternion.cpp	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,817 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/01/19: Etienne Lachance
+    -Removed function Exp and Ln.
+    -Added function power and Log.
+    -Fixed bugs in Slerp, Slerp_prime, Squad and Squad_prime.
+
+2003/05/23: Etienne Lachance
+    -Added the following member function -=, +=, *=, /=, Exp, Ln, dot, d_dt, E
+    -Added functions Integ_Trap_quat, Slerp, Slerp_prime, Squad, Squad_prime,
+
+2004/05/14: Etienne Lachance
+    -Replaced vec_x_prod by CrossProduct.
+
+2004/05/21: Etienne Lachance
+   -Added comments that can be used with Doxygen.
+
+2004/07/01: Etienne Lachance
+   -Replaced vec_dot_prod by DotProdut of Newmat library.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+    -Fixed problem in constructor using float as Real type
+-------------------------------------------------------------------------------
+*/
+
+
+/*!
+  @file quaternion.cpp
+  @brief Quaternion functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: quaternion.cpp,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "quaternion.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+Quaternion::Quaternion()
+//! @brief Constructor.
+{
+   s_ = 1.0;
+   v_ = ColumnVector(3);
+   v_ = 0.0;
+}
+
+Quaternion::Quaternion(const Quaternion & q)
+//! @brief Constructor.
+{
+   s_ = q.s_;
+   v_ = q.v_;
+}
+
+Quaternion::Quaternion(const Real angle, const ColumnVector & axis)
+//! @brief Constructor.
+{
+   if(axis.Nrows() != 3)
+   {
+      cerr << "Quaternion::Quaternion, size of axis != 3" << endl;
+      exit(1);
+   }
+
+   // make sure axis is a unit vector
+   Real norm_axis = sqrt(DotProduct(axis, axis));
+
+   if(norm_axis != 1)
+   {
+      cerr << "Quaternion::Quaternion(angle, axis), axis is not unit" << endl;
+      cerr << "Make the axis unit." << endl;
+      v_ = sin(angle/2) * axis/norm_axis;
+   }
+   else
+      v_ = sin(angle/2) * axis;
+
+   s_ = cos(angle/2);
+}
+
+Quaternion::Quaternion(const Real s_in, const Real v1, const Real v2,
+                       const Real v3)
+//!  @brief Constructor.
+{
+   s_ = s_in;
+   v_ = ColumnVector(3);
+   v_(1) = v1;
+   v_(2) = v2;
+   v_(3) = v3;
+}
+
+Quaternion::Quaternion(const Matrix & R)
+/*!
+  @brief Constructor.
+
+  Cite_: Dam.
+  The unit quaternion obtained from a matrix (see Quaternion::R())
+  \f[
+  R(s,v) =
+   \left[
+    \begin{array}{ccc}
+      s^2+v_1^2-v_2^2-v_3^2 & 2v_1v_2+2sv_3 & 2v_1v_3-2sv_2 \\
+      2v_1v_2-2sv_3 & s^2-v_1^2+v_2^2-v_3^2 & 2v_2v_3+2sv_1 \\
+      2v_1v_3+2sv_2 &2v_2v_3-2sv_1 & s^2-v_1^2-v_2^2+v_3^2  
+    \end{array}
+   \right]
+  \f]
+  
+  First we find \f$s\f$:
+  \f[
+   R_{11} + R_{22} + R_{33} + R_{44} = 4s^2
+  \f]
+  Now the other values are:
+  \f[
+    s = \pm \frac{1}{2}\sqrt{R_{11} + R_{22} + R_{33} + R_{44}}
+  \f]
+  \f[
+   v_1 = \frac{R_{32}-R_{23}}{4s}
+  \f]
+  \f[
+   v_2 = \frac{R_{13}-R_{31}}{4s}
+  \f]
+  \f[
+   v_3 = \frac{R_{21}-R_{12}}{4s}
+  \f]
+
+  The sign of \f$s\f$ cannot be determined. Depending on the choice of the sign 
+  for s the sign of \f$v\f$ change as well. Thus the quaternions \f$q\f$ and 
+  \f$-q\f$ represent the same rotation, but the interpolation curve changed with
+  the choice of the sign. 
+  A positive sign has been chosen.
+*/
+{
+   if( (R.Nrows() == 3) && (R.Ncols() == 3) ||
+         (R.Nrows() == 4) && (R.Ncols() == 4) )
+   {
+      Real tmp = fabs(R(1,1) + R(2,2) + R(3,3) + 1);
+      s_ = 0.5*sqrt(tmp);
+      if(v_.Nrows() != 3)
+         v_ = ColumnVector(3);
+
+      if(s_ > EPSILON)
+      {
+         v_(1) = (R(3,2)-R(2,3))/(4*s_);
+         v_(2) = (R(1,3)-R(3,1))/(4*s_);
+         v_(3) = (R(2,1)-R(1,2))/(4*s_);
+      }
+      else
+      {
+         // |w| <= 1/2
+         static int s_iNext[3] = { 2, 3, 1 };
+         int i = 1;
+         if ( R(2,2) > R(1,1) )
+            i = 2;
+         if ( R(3,3) > R(2,2) )
+            i = 3;
+         int j = s_iNext[i-1];
+         int k = s_iNext[j-1];
+
+         Real fRoot = sqrt(R(i,i)-R(j,j)-R(k,k) + 1.0);
+
+         Real *tmp[3] = { &v_(1), &v_(2), &v_(3) };
+         *tmp[i-1] = 0.5*fRoot;
+         fRoot = 0.5/fRoot;
+         s_ = (R(k,j)-R(j,k))*fRoot;
+         *tmp[j-1] = (R(j,i)+R(i,j))*fRoot;
+         *tmp[k-1] = (R(k,i)+R(i,k))*fRoot;
+      }
+
+   }
+   else
+      cerr << "Quaternion::Quaternion: matrix input is not 3x3 or 4x4" << endl;
+}
+
+Quaternion & Quaternion::operator=(const Quaternion & q)
+//! @brief Overload = operator.
+{
+   s_ = q.s_;
+   v_ = q.v_;
+
+   return *this;
+}
+
+Quaternion Quaternion::operator+(const Quaternion & rhs)const
+/*!
+  @brief Overload + operator.
+
+  The quaternion addition is 
+  \f[
+  q_1 + q_2 = [s_1, v_1] + [s_2, v_2] = [s_1+s_2, v_1+v_2]
+  \f]
+
+  The result is not necessarily a unit quaternion even if \f$q_1\f$ and
+  \f$q_2\f$ are unit quaternions.
+*/
+{
+   Quaternion q;
+   q.s_ = s_ + rhs.s_;
+   q.v_ = v_ + rhs.v_;
+
+   return q;
+}
+
+Quaternion Quaternion::operator-(const Quaternion & rhs)const
+/*!
+  @brief Overload - operator.
+
+  The quaternion soustraction is 
+  \f[
+  q_1 - q_2 = [s_1, v_1] - [s_2, v_2] = [s_1-s_2, v_1-v_2]
+  \f]
+
+  The result is not necessarily a unit quaternion even if \f$q_1\f$ and
+  \f$q_2\f$ are unit quaternions.
+*/
+{
+   Quaternion q;
+   q.s_ = s_ - rhs.s_;
+   q.v_ = v_ - rhs.v_;
+
+   return q;
+}
+
+Quaternion Quaternion::operator*(const Quaternion & rhs)const
+/*!
+  @brief Overload * operator.
+
+  The multiplication of two quaternions is
+
+  \f[
+  q = q_1q_2 = [s_1s_2 - v_1\cdot v_2, v_1 \times v_2 + s_1v_2 + s_2v_1]
+  \f]
+  where \f$\cdot\f$ and \f$\times\f$ denote the scalar and vector product
+  in \f$R^3\f$ respectively.
+
+  If \f$q_1\f$ and \f$q_2\f$ are unit quaternions, then q will also be a 
+  unit quaternion.
+*/
+{
+   Quaternion q;
+   q.s_ = s_ * rhs.s_ - DotProduct(v_, rhs.v_);
+   q.v_ = s_ * rhs.v_ + rhs.s_ * v_ + CrossProduct(v_, rhs.v_);
+
+   return q;
+}
+
+Quaternion Quaternion::operator*(const Real c)const
+/*!
+  @brief Overload * operator, multiplication by a scalar.
+
+  \f$q = [s, v]\f$ and let \f$r \in R\f$. Then
+  \f$rq = qr = [r, 0][s, v] = [rs, rv]\f$
+
+  The result is not necessarily a unit quaternion even if \f$q\f$ 
+  is a unit quaternions.
+*/
+{
+   Quaternion q;
+   q.s_ = s_ * c;
+   q.v_ = v_ * c;
+
+   return q;
+}
+
+Quaternion Quaternion::operator/(const Quaternion & rhs)const
+//! @brief Overload / operator.
+{
+//   Quaternion q = rhs;
+//   q = *this * q.conjugate();
+//   q = *this * q.i();
+
+//   return q;
+
+    return *this*rhs.i();
+}
+
+Quaternion Quaternion::operator/(const Real c)const
+/*!
+  @brief Overload / operator, division by a scalar.
+
+  Same explanation as multiplication by scaler.
+*/
+{
+   Quaternion q;
+   q.s_ = s_ / c;
+   q.v_ = v_ / c;
+
+   return q;
+}
+
+void Quaternion::set_v(const ColumnVector & v)
+//! @brief Set quaternion vector part.
+{
+   if(v.Nrows() == 3)
+      v_ = v;
+   else
+       cerr << "Quaternion::set_v: input has a wrong size." << endl;
+}
+
+Quaternion Quaternion::conjugate()const
+/*!
+  @brief Conjugate.
+
+  The conjugate of a quaternion \f$q = [s, v]\f$ is
+  \f$q^{*} = [s, -v]\f$
+*/
+{
+   Quaternion q;
+   q.s_ = s_;
+   q.v_ = -1*v_;
+
+   return q;
+}
+
+Real Quaternion::norm()const 
+/*!
+  @brief Return the quaternion norm.
+
+  The norm of quaternion is defined by
+  \f[
+  N(q) = s^2 + v\cdot v
+  \f]
+*/
+{ 
+  return( sqrt(s_*s_ + DotProduct(v_, v_)) );
+}
+
+Quaternion & Quaternion::unit()
+//! @brief Normalize a quaternion.
+{
+   Real tmp = norm();
+   if(tmp > EPSILON)
+   {
+      s_ = s_/tmp;
+      v_ = v_/tmp;
+   }
+   return *this;
+}
+
+Quaternion Quaternion::i()const 
+/*!
+  @brief Quaternion inverse.
+  \f[
+    q^{-1} = \frac{q^{*}}{N(q)}
+  \f]
+  where \f$q^{*}\f$ and \f$N(q)\f$ are the quaternion
+  conjugate and the quaternion norm respectively.
+*/
+{ 
+    return conjugate()/norm();
+}
+
+Quaternion Quaternion::exp() const
+/*!
+  @brief Exponential of a quaternion.
+
+  Let a quaternion of the form \f$q = [0, \theta v]\f$, q is not
+  necessarily a unit quaternion. Then the exponential function
+  is defined by \f$q = [\cos(\theta),v \sin(\theta)]\f$.
+*/
+{
+   Quaternion q;
+   Real theta = sqrt(DotProduct(v_,v_)),
+                sin_theta = sin(theta);
+
+   q.s_ = cos(theta);
+   if ( fabs(sin_theta) > EPSILON)
+      q.v_ = v_*sin_theta/theta;
+   else
+      q.v_ = v_;
+
+   return q;
+}
+
+Quaternion Quaternion::power(const Real t) const
+{
+   Quaternion q = (Log()*t).exp();
+
+   return q;
+}
+
+Quaternion Quaternion::Log()const
+/*!
+  @brief Logarithm of a unit quaternion.
+
+  The logarithm function of a unit quaternion 
+  \f$q = [\cos(\theta), v \sin(\theta)]\f$ is defined as 
+  \f$log(q) = [0, v\theta]\f$. The result is not necessary 
+  a unit quaternion.
+*/
+{
+   Quaternion q;
+   q.s_ = 0;
+   Real theta = acos(s_),
+                sin_theta = sin(theta);
+
+   if ( fabs(sin_theta) > EPSILON)
+      q.v_ = v_/sin_theta*theta;
+   else
+      q.v_ = v_;
+
+   return q;
+}
+
+Quaternion Quaternion::dot(const ColumnVector & w, const short sign)const
+/*!
+  @brief Quaternion time derivative.
+
+  The quaternion time derivative, quaternion propagation equation, is
+  \f[
+    \dot{s} = - \frac{1}{2}v^Tw_{_0}
+  \f]
+  \f[
+    \dot{v} = \frac{1}{2}E(s,v)w_{_0}
+  \f]
+  \f[
+    E = sI - S(v)
+  \f]
+  where \f$w_{_0}\f$ is the angular velocity vector expressed in the base
+  frame. If the vector is expressed in the object frame, \f$w_{_b}\f$, the
+  time derivative becomes
+  \f[
+   \dot{s} = - \frac{1}{2}v^Tw_{_b}
+  \f]
+  \f[
+   \dot{v} = \frac{1}{2}E(s,v)w_{_b}
+  \f]
+  \f[
+   E = sI + S(v)
+  \f]
+*/
+{
+   Quaternion q;
+   Matrix tmp;
+
+   tmp = -0.5*v_.t()*w;
+   q.s_ = tmp(1,1);
+   q.v_ = 0.5*E(sign)*w;
+
+   return q;
+}
+
+ReturnMatrix Quaternion::E(const short sign)const
+/*!
+  @brief Matrix E.
+
+  See Quaternion::dot for explanation.
+*/
+{
+   Matrix E(3,3), I(3,3);
+   I << threebythreeident;
+
+   if(sign == BODY_FRAME)
+      E = s_*I + x_prod_matrix(v_);
+   else
+      E = s_*I - x_prod_matrix(v_);
+
+   E.Release();
+   return E;
+}
+
+Real Quaternion::dot_prod(const Quaternion & q)const
+/*!
+  @brief Quaternion dot product.
+
+  The dot product of quaternion is defined by  
+  \f[
+  q_1\cdot q_2 = s_1s_2 + v_1 \cdot v_2
+  \f]
+*/
+{
+   return (s_*q.s_ + v_(1)*q.v_(1) + v_(2)*q.v_(2) + v_(3)*q.v_(3));
+}
+
+ReturnMatrix Quaternion::R()const
+/*!
+  @brief Rotation matrix from a unit quaternion.
+
+  \f$p'=qpq^{-1} = Rp\f$ where \f$p\f$ is a vector, \f$R\f$ a rotation
+  matrix and \f$q\f$ q quaternion. The rotation matrix obtained from a 
+  quaternion is then
+  \f[
+  R(s,v) = (s^2 - v^Tv)I + 2vv^T - 2s S(v)
+  \f]
+  \f[
+  R(s,v) =
+   \left[
+    \begin{array}{ccc}
+      s^2+v_1^2-v_2^2-v_3^2 & 2v_1v_2+2sv_3 & 2v_1v_3-2sv_2 \\
+      2v_1v_2-2sv_3 & s^2-v_1^2+v_2^2-v_3^2 & 2v_2v_3+2sv_1 \\
+      2v_1v_3+2sv_2 &2v_2v_3-2sv_1 & s^2-v_1^2-v_2^2+v_3^2  
+    \end{array}
+   \right]
+  \f]
+  where \f$S(\cdot)\f$ is the cross product matrix defined by
+  \f[
+    S(u) = 
+     \left[
+      \begin{array}{ccc}
+        0 & -u_3 & u_2 \\
+	u_3 &0 & -u_1  \\
+	-u_2 & u_1 & 0 \\
+      \end{array}
+     \right]
+  \f]
+*/
+{
+   Matrix R(3,3);
+   R << threebythreeident;
+   R = (1 - 2*DotProduct(v_, v_))*R + 2*v_*v_.t() + 2*s_*x_prod_matrix(v_);
+
+   R.Release();
+   return R;
+}
+
+ReturnMatrix Quaternion::T()const
+/*!
+  @brief Transformation matrix from a quaternion.
+
+  See Quaternion::R() for equations.
+*/
+{
+   Matrix T(4,4);
+   T << fourbyfourident;
+   T.SubMatrix(1,3,1,3) = (1 - 2*DotProduct(v_, v_))*T.SubMatrix(1,3,1,3)
+                          + 2*v_*v_.t() + 2*s_*x_prod_matrix(v_);
+   T.Release();
+   return T;
+}
+
+// -------------------------------------------------------------------------------------
+
+ReturnMatrix Omega(const Quaternion & q, const Quaternion & q_dot)
+/*!
+  @brief Return angular velocity from a quaternion and it's time derivative
+
+  See Quaternion::dot for explanation.
+*/
+{
+   Matrix A, B, M;
+   UpperTriangularMatrix U;
+   ColumnVector w(3);
+   A = 0.5*q.E(BASE_FRAME);
+   B = q_dot.v();
+   if(A.Determinant())
+   {
+      QRZ(A,U);             //QR decomposition
+      QRZ(A,B,M);
+      w = U.i()*M;
+   }
+   else
+      w = 0;
+
+   w.Release();
+   return w;
+}
+
+short Integ_quat(Quaternion & dquat_present, Quaternion & dquat_past,
+                 Quaternion & quat, const Real dt)
+//! @brief Trapezoidal quaternion integration.
+{
+   if (dt < 0)
+   {
+      cerr << "Integ_Trap(quat1, quat2, dt): dt < 0. dt is set to 0." << endl;
+      return -1;
+   }
+
+   // Quaternion algebraic constraint
+   //  Real Klambda = 0.5*(1 - quat.norm_sqr());
+
+   dquat_present.set_s(dquat_present.s() );//+ Klambda*quat.s());
+   dquat_present.set_v(dquat_present.v() ); //+ Klambda*quat.v());
+
+   quat.set_s(quat.s() + Integ_Trap_quat_s(dquat_present, dquat_past, dt));
+   quat.set_v(quat.v() + Integ_Trap_quat_v(dquat_present, dquat_past, dt));
+
+   dquat_past.set_s(dquat_present.s());
+   dquat_past.set_v(dquat_present.v());
+
+   quat.unit();
+
+   return 0;
+}
+
+Real Integ_Trap_quat_s(const Quaternion & present, Quaternion & past,
+                       const Real dt)
+//! @brief Trapezoidal quaternion scalar part integration.
+{
+   Real integ = 0.5*(present.s()+past.s())*dt;
+   past.set_s(present.s());
+   return integ;
+}
+
+ReturnMatrix Integ_Trap_quat_v(const Quaternion & present, Quaternion & past,
+                               const Real dt)
+//! @brief Trapezoidal quaternion vector part integration.
+{
+   ColumnVector integ = 0.5*(present.v()+past.v())*dt;
+   past.set_v(present.v());
+   integ.Release();
+   return integ;
+}
+
+Quaternion Slerp(const Quaternion & q0, const Quaternion & q1, const Real t)
+/*!
+  @brief Spherical Linear Interpolation.
+
+  Cite_:Dam
+
+  The quaternion \f$q(t)\f$ interpolate the quaternions \f$q_0\f$ 
+  and \f$q_1\f$ given the parameter \f$t\f$ along the quaternion sphere.
+  \f[
+   q(t) = c_0(t)q_0 + c_1(t)q_1
+  \f]
+  where \f$c_0\f$ and \f$c_1\f$ are real functions with \f$0\leq t \leq 1\f$.
+  As \f$t\f$ varies between 0 and 1. the values \f$q(t)\f$ varies uniformly 
+  along the circular arc from \f$q_0\f$ and \f$q_1\f$. The angle between 
+  \f$q(t)\f$ and \f$q_0\f$ is \f$\cos(t\theta)\f$ and the angle between
+  \f$q(t)\f$ and \f$q_1\f$ is \f$\cos((1-t)\theta)\f$. Taking the dot product
+  of \f$q(t)\f$ and \f$q_0\f$ yields
+  \f[
+   \cos(t\theta) = c_0(t) + \cos(\theta)c_1(t)
+  \f]
+  and taking the dot product of \f$q(t)\f$ and \f$q_1\f$ yields
+  \f[
+   \cos((1-t)\theta) = \cos(\theta)c_0(t) + c_1(t)
+  \f]
+  These are two equations with \f$c_0\f$ and \f$c_1\f$. The solution is
+  \f[
+   c_0 = \frac{\sin((1-t)\theta)}{\sin(\theta)}
+  \f]
+  \f[
+   c_1 = \frac{\sin(t\theta)}{sin(\theta)}
+  \f]
+  The interpolation is then
+  \f[
+   Slerp(q_0, q_1, t) = \frac{q_0\sin((1-t)\theta)+q_1\sin(t\theta)}{\sin(\theta)}
+  \f]
+  If \f$q_0\f$ and \f$q_1\f$ are unit quaternions the \f$q(t)\f$ is also a unit
+  quaternions. For unit quaternions we have
+  \f[
+   Slerp(q_0, q_1, t) = q_0(q_0^{-1}q_1)^t
+  \f]
+  For t = 0 and t = 1 we have
+  \f[
+   q_0 = Slerp(q_0, q_1, 0)
+  \f]
+  \f[
+   q_1 = Slerp(q_0, q_1, 1)
+  \f]
+  It is customary to choose the sign G on q1 so that q0.Gq1 >=0 (the angle
+  between q0 ang Gq1 is acute). This choice avoids extra spinning caused
+  by the interpolated rotations.
+*/
+{
+   if( (t < 0) || (t > 1) )
+      cerr << "Slerp(q0, q1, t): t < 0 or t > 1. t is set to 0." << endl;
+
+   if(q0.dot_prod(q1) >= 0)
+      return q0*((q0.i()*q1).power(t));
+   else
+      return  q0*((q0.i()*-1*q1).power(t));
+}
+
+Quaternion Slerp_prime(const Quaternion & q0, const Quaternion & q1,
+                       const Real t)
+/*!
+  @brief Spherical Linear Interpolation derivative.
+
+  Cite_: Dam
+
+  The derivative of the function \f$q^t\f$ where \f$q\f$ is a constant
+  unit quaternion is
+  \f[
+   \frac{d}{dt}q^t = q^t log(q)
+  \f]
+  Using the preceding equation the Slerp derivative is then
+  \f[
+   Slerp'(q_0, q_1, t) = q_0(q_0^{-1}q_1)^t log(q_0^{-1}q_1)
+  \f]
+
+  It is customary to choose the sign G on q1 so that q0.Gq1 >=0 (the angle
+  between q0 ang Gq1 is acute). This choice avoids extra spinning caused
+  by the interpolated rotations.
+  The result is not necessary a unit quaternion.
+*/
+
+{
+   if( (t < 0) || (t > 1) )
+      cerr << "Slerp_prime(q0, q1, t): t < 0 or t > 1. t is set to 0." << endl;
+
+   if(q0.dot_prod(q1) >= 0)
+      return Slerp(q0, q1, t)*(q0.i()*q1).Log();
+   else
+      return Slerp(q0, q1, t)*(q0.i()*-1*q1).Log();
+}
+
+Quaternion Squad(const Quaternion & p, const Quaternion & a, const Quaternion & b,
+                 const Quaternion & q, const Real t)
+/*!
+  @brief Spherical Cubic Interpolation.
+
+  Cite_: Dam
+
+  Let four quaternions be \f$q_i\f$ (p), \f$s_i\f$ (a), \f$s_{i+1}\f$ (b) and \f$q_{i+1}\f$ 
+  (q) be the ordered vertices of a quadrilateral. Obtain c from \f$q_i\f$ to \f$q_{i+1}\f$ 
+  interpolation. Obtain d from \f$s_i\f$ to \f$s_{i+1}\f$ interpolation. Obtain e,
+  the final result, from c to d interpolation.
+  \f[
+   Squad(q_i, s_i, s_{i+1}, q_{i+1}, t) = Slerp(Slerp(q_i,q_{i+1},t),Slerp(s_i,s_{i+1},t), 2t(1-t))
+  \f]
+  The intermediate quaternion \f$s_i\f$ and \f$s_{i+1}\f$ are given by
+  \f[
+   s_i = q_i exp\Big ( - \frac{log(q_i^{-1}q_{i+1}) + log(q_i^{-1}q_{i-1})}{4}\Big )
+  \f]
+*/
+{
+   if( (t < 0) || (t > 1) )
+      cerr << "Squad(p,a,b,q, t): t < 0 or t > 1. t is set to 0." << endl;
+
+   return Slerp(Slerp(p,q,t),Slerp(a,b,t),2*t*(1-t));
+}
+
+Quaternion Squad_prime(const Quaternion & p, const Quaternion & a, const Quaternion & b,
+                       const Quaternion & q, const Real t)
+/*!
+  @brief Spherical Cubic Interpolation derivative.
+
+  Cite_: www.magic-software.com
+
+
+  The derivative of the function \f$q^t\f$ where \f$q\f$ is a constant
+  unit quaternion is
+  \f[
+   \frac{d}{dt}q^t = q^t log(q)
+  \f]
+  Recalling that \f$log(q) = [0, v\theta]\f$ (see Quaternion::Log()). If the power
+  is a function we have
+  \f[
+   \frac{d}{dt}q^{f(t)} = f'(t)q^{f(t)}log(q)
+  \f]
+  If \f$q\f$ is a function of time and the power is differentiable function of time
+  we have
+  \f[
+  \frac{d}{dt}(q(t))^{f(t)} = f'(t)(q(t))^{f(t)}log(q) + f(t)(q(t))^{f(t)-1}q'(t)
+  \f]
+  Using these last three equations Squad derivative can be define. Let 
+  \f$U(t)=Slerp(p,q,t)\f$, \f$V(t)=Slerp(q,b,t)\f$, \f$W(t)=U(t)^{-1}V(t)\f$. We then
+  have \f$Squad(p,a,b,q,t)=Slerp(U(t),V(t),2t(1-t))=U(t)W(t)^{2t(1-t)}\f$
+
+  \f[
+   Squad'(p,a,b,q,t) = \frac{d}{dt}\Big [ UW^{2t(1-t)}\Big ]
+  \f]
+  \f[
+   Squad'(p,a,b,q,t) = U\frac{d}{dt}\Big [ W^{2t(1-t)}\Big ] + U'\Big [W^{2t(1-t)}\Big]
+  \f]
+  \f[
+   Squad'(p,a,b,q,t) = U\Big[(2-4t)W^{2t(1-t)}log(W)+2t(1-t)W^{2t(1-t)-1}W'\Big]
+    + U'\Big[W^{2t(1-t)} \Big]
+  \f]
+  where \f$U'=Ulog(p^{-1}q)\f$, \f$V'=Vlog(a^{-1},b)\f$, \f$W'=U^{-1}V'-U^{-2}U'V\f$
+  
+
+  The result is not necessarily a unit quaternion even if all the input quaternions are unit.
+*/
+{
+   if( (t < 0) || (t > 1) )
+      cerr << "Squad_prime(p,a,b,q, t): t < 0 or t > 1. t is set to 0." << endl;
+
+   Quaternion q_squad,
+   U = Slerp(p, q, t),
+       V = Slerp(a, b, t),
+           W = U.i()*V,
+               U_prime = U*(p.i()*q).Log(),
+                         V_prime = V*(a.i()*b).Log(),
+                                   W_prime = U.i()*V_prime - U.power(-2)*U_prime*V;
+
+   q_squad = U*( W.power(2*t*(1-t))*W.Log()*(2-4*t) + W.power(2*t*(1-t)-1)*W_prime*2*t*(1-t) )
+             + U_prime*( W.power(2*t*(1-t)) );
+
+   return q_squad;
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
Index: Motion/roboop/quaternion.h
===================================================================
RCS file: Motion/roboop/quaternion.h
diff -N Motion/roboop/quaternion.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/quaternion.h	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,148 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+Reference:
+
+[1] J.C.K. Chou, "Quaternion Kinematic and Dynamic Differential Equations", 
+    IEEE Transaction on Robotics and Automation, vol 8, p53-64.
+
+[2] S. Chiaverini, B. Siciliano, "The Unit Quaternion: A Useful Tool for
+    Inverse Kinematics of Robot Manipulators", Systems Analysis, Modelling
+    and Simulation, vol. 35, pp.45-60, 1999.
+
+[3] C. Natale, "Quaternion-Based Representation of Rigid Bodies Orientation",
+    PRISMA LAB, PRISMA Technical Report no. 97-05, Oct 1997.
+
+[4] M. Lillholm, E.B. Dam, M. Koch, "Quaternions, Interpolation and Animation",
+    Technical Report DIKU-TR-98/5, University of Copenhagen, July 1998.
+
+[5] D. Eberly, "Quaternion Algebra and Calculus", Magic Software Inc.,
+    http://www.magic-software.com, March 1999.
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/05/28: Etienne Lachance
+    -Added functions Slerp, Slerp_prime, Squad, Squad_prime.
+    -Added the following member functions:+=, -=, *=, /=, Exp, d_dt, Ln, Ln_4, E
+
+2004/05/21: Etienne Lachance
+   -Added Doxygen comments.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+------------------------------------------------------------------------------
+*/
+
+
+#ifndef QUATERNION_H
+#define QUATERNION_H
+
+/*!
+  @file quaternion.h
+  @brief Quaternion class.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_quat_rcsid[] = "$Id: quaternion.h,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#define BASE_FRAME 0
+#define BODY_FRAME 1
+#define EPSILON 0.0000001
+
+/*!
+  @class Quaternion
+  @brief Quaternion class definition.
+*/
+class Quaternion
+{
+public:
+   Quaternion();
+   Quaternion(const Quaternion & q);
+   Quaternion(const Real angle_in_rad, const ColumnVector & axis);
+   Quaternion(const Real s, const Real v1, const Real v2,
+              const Real v3);
+   Quaternion(const Matrix & R);
+
+   Quaternion & operator=(const Quaternion & q);
+   Quaternion   operator+(const Quaternion & q)const;
+   Quaternion   operator-(const Quaternion & q)const;
+   Quaternion   operator*(const Quaternion & q)const;
+   Quaternion   operator*(const Real c)const;
+   Quaternion   operator/(const Quaternion & q)const;
+   Quaternion   operator/(const Real c)const;
+   Quaternion   conjugate()const;
+
+//   Quaternion   i()const { return conjugate(); }
+   Quaternion   i()const;
+   Quaternion & unit(); 
+   Quaternion   exp() const;
+   Quaternion   power(const Real t) const;
+   Quaternion   Log() const;
+
+   Quaternion   dot(const ColumnVector & w, const short sign)const;
+   ReturnMatrix E(const short sign)const;
+
+   Real         norm()const;
+   Real         dot_prod(const Quaternion & q)const;
+   Real         s()const { return s_; }        //!< Return scalar part.
+   void         set_s(const Real s){ s_ = s; } //!< Set scalar part.
+   ReturnMatrix v()const { return v_; }        //!< Return vector part.
+   void         set_v(const ColumnVector & v); //!< Set vector part.
+   ReturnMatrix R()const;
+   ReturnMatrix T()const;
+
+private:
+   Real s_;         //!< Quaternion scalar part.
+   ColumnVector v_; //!< Quaternion vector part.
+};
+
+// ----------------------------------------------------------------------------
+
+ReturnMatrix Omega(const Quaternion & q, const Quaternion & q_dot);
+
+short Integ_quat(Quaternion & dquat_present, Quaternion & dquat_past,
+                 Quaternion & quat, const Real dt);
+Real Integ_Trap_quat_s(const Quaternion & present, Quaternion & past,
+                       const Real dt);
+ReturnMatrix Integ_Trap_quat_v(const Quaternion & present, Quaternion & past,
+                               const Real dt);
+
+Quaternion Slerp(const Quaternion & q0, const Quaternion & q1, const Real t);
+Quaternion Slerp_prime(const Quaternion & q0, const Quaternion & q1, const Real t);
+
+Quaternion Squad(const Quaternion & p, const Quaternion & a, const Quaternion & b,
+                 const Quaternion & q, const Real t);
+Quaternion Squad_prime(const Quaternion & p, const Quaternion & a, const Quaternion & b,
+                       const Quaternion & q, const Real t);
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
Index: Motion/roboop/readme.txt
===================================================================
RCS file: Motion/roboop/readme.txt
diff -N Motion/roboop/readme.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/readme.txt	14 Jul 2004 02:29:35 -0000	1.2
@@ -0,0 +1,68 @@
+This is the ROBOOP readme.txt file
+==================================
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+
+DESCRIPTION
+===========
+
+This package (ROBOOP) is a C++ robotics object oriented programming toolbox 
+suitable for synthesis, and simulation of robotic manipulator models in an 
+environment that provides "MATLAB like" features for the treatment of 
+matrices. Its is a portable tool that does not require the use of commercial 
+software. A class named Robot provides the implementation of the kinematics, 
+the dynamics and the linearized dynamics of serial robotic manipulators.
+
+
+WHERE CAN GET THIS PACKAGE
+==========================
+
+Program source and documentation are available from the URL: 
+        http://www.cours.polymtl.ca/roboop
+
+
+DOCUMENTATION
+=============
+
+The documentation is provided in postscript format:
+        docs/robot.ps
+
+Documentation in html format is available from the URL: 
+        http://www.cours.polymtl.ca/roboop
+
+
+
+VERSION
+=======
+
+This version 1.12 of the package:
+
+Revisions of the source code are detailed in the file:
+
+revision.txt
+
+See the documentation for the version history.
Index: Motion/roboop/revisions.txt
===================================================================
RCS file: Motion/roboop/revisions.txt
diff -N Motion/roboop/revisions.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/revisions.txt	14 Jul 2004 02:29:35 -0000	1.2
@@ -0,0 +1,38 @@
+ROBOOP source code revisions
+============================
+Id: bench.cpp,v 1.15 2004/07/06 02:16:36
+Id: clik.cpp,v 1.5 2004/07/06 02:16:36
+Id: comp_dq.cpp,v 1.17 2004/07/06 02:16:36
+Id: comp_dqp.cpp,v 1.16 2004/07/06 02:16:36
+Id: config.cpp,v 1.11 2004/07/06 02:16:36
+Id: controller.cpp,v 1.1 2004/07/06 02:16:36
+Id: control_select.cpp,v 1.1 2004/07/06 02:16:36
+Id: delta_t.cpp,v 1.16 2004/07/06 02:16:36
+Id: demo_2dof_pd.cpp,v 1.1 2004/07/06 02:16:36
+Id: demo.cpp,v 1.28 2004/07/06 02:16:36
+Id: dynamics.cpp,v 1.31 2004/07/06 02:16:36
+Id: dynamics_sim.cpp,v 1.1 2004/07/06 02:16:36
+Id: gnugraph.cpp,v 1.36 2004/07/06 02:16:36
+Id: homogen.cpp,v 1.12 2004/07/06 02:16:36
+Id: invkine.cpp,v 1.2 2004/07/06 02:16:36
+Id: kinemat.cpp,v 1.29 2004/07/06 02:16:36
+Id: quaternion.cpp,v 1.16 2004/07/06 02:16:36
+Id: robot.cpp,v 1.39 2004/07/06 02:16:37
+Id: rtest.cpp,v 1.13 2004/07/06 02:16:37
+Id: sensitiv.cpp,v 1.13 2004/07/06 02:16:37
+Id: trajectory.cpp,v 1.5 2004/07/06 02:16:37
+Id: utils.cpp,v 1.22 2004/07/06 02:16:37
+Id: clik.h,v 1.5 2004/07/06 02:16:36
+Id: config.h,v 1.11 2004/07/06 02:16:36
+Id: controller.h,v 1.1 2004/07/06 02:16:36
+Id: control_select.h,v 1.1 2004/07/06 02:16:36
+Id: dynamics_sim.h,v 1.1 2004/07/06 02:16:36
+Id: gnugraph.h,v 1.8 2004/07/06 02:16:36
+Id: quaternion.h,v 1.10 2004/07/06 02:16:36
+Id: robot.h,v 1.45 2004/07/06 02:16:37
+Id: trajectory.h,v 1.7 2004/07/06 02:16:37
+Id: utils.h,v 1.6 2004/07/06 02:16:37
+Id: makefile.bc5,v 1.14 2004/07/07 02:47:43
+Id: makefile.gcc,v 1.14 2004/07/04 03:11:53
+Id: makefile.gw32,v 1.11 2004/07/04 03:11:53
+Id: makefile.vcpp,v 1.9 2004/07/07 02:47:43
Index: Motion/roboop/robdocs.tar.gz
===================================================================
RCS file: Motion/roboop/robdocs.tar.gz
diff -N Motion/roboop/robdocs.tar.gz
Binary files /dev/null and /tmp/cvsJDNEgR differ
Index: Motion/roboop/robot.cpp
===================================================================
RCS file: Motion/roboop/robot.cpp
diff -N Motion/roboop/robot.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/robot.cpp	12 Oct 2004 19:50:25 -0000	1.18
@@ -0,0 +1,1827 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Merge classes Link and mLink into Link.
+   -Added Robot_basic class, which is base class of Robot and mRobot.
+   -Use try/catch statement in dynamic memory allocation.
+   -Added member functions set_qp and set_qpp in Robot_basic.
+   -It is now possible to specify a min and max value of joint angle in
+    all the robot constructor.
+
+2003/05/18: Etienne Lachance
+   -Initialize the following vectors to zero in Ro_basic constructors: w, wp, vp, dw, dwp, dvp.
+   -Added vector z0 in robot_basic.
+
+2004/01/23: Etienne Lachance
+   -Added const in non reference argument for all functions.
+
+2004/03/01: Etienne Lachance
+   -Added non member function perturb_robot.
+
+2004/03/21: Etienne Lachance
+   -Added the following member functions: set_mc, set_r, set_I.
+
+2004/04/19: Etienne Lachane
+   -Added and fixed Robot::robotType_inv_kin(). First version of this member function
+    has been done by Vincent Drolet.
+
+2004/04/26: Etienne Lachance
+   -Added member functions Puma_DH, Puma_mDH, Rhino_DH, Rhino_mDH.
+
+2004/05/21: Etienne Lachance
+   -Added Doxygen comments.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+    -Modified Link constructor, Robot_basic constructor, Link::transform and
+     Link::get_q functions in order to added joint_offset.
+
+2004/07/13: Ethan Tira-Thompson
+    -if joint_offset isn't defined in the config file, it is set to theta
+
+2004/07/16: Ethan Tira-Thompson
+    -Added Link::immobile flag, accessor functions, and initialization code
+    -Added get_available_q* functions, modified set_q so it can take a list of 
+     length `dof' or `get_available_dof()'.
+
+2004/08/04: Ethan Tira-Thompson
+    -Added check to Link::transform() so it shortcuts math if q is unchanged
+    
+2004/09/01: Ethan Tira-Thompson
+    -Added constructor for instantiation from already-read config file.
+     This saves time when having to reconstruct repeatedly with slow disks
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file robot.cpp
+  @brief Initialisation of differents robot class.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: robot.cpp,v 1.18 2004/10/12 19:50:25 ejt Exp $";
+
+#include "robot.h"
+#include <time.h>
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+//! @brief Used to initialize a \f$4\times 4\f$ matrix.
+Real fourbyfourident[] = {1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0};
+
+//! @brief Used to initialize a \f$3\times 3\f$ matrix.
+Real threebythreeident[] ={1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0};
+
+/*!
+  @fn Link::Link(const int jt, const Real it, const Real id,
+        const Real ia, const Real ial, const Real theta_min,
+        const Real theta_max, const Real it_off, const Real mass,
+        const Real cmx, const Real cmy, const Real cmz,
+        const Real ixx, const Real ixy, const Real ixz,
+        const Real iyy, const Real iyz, const Real izz,
+        const Real iIm, const Real iGr, const Real iB,
+        const Real iCf, const bool dh, const bool min_inertial_para)
+  @brief Constructor.
+*/
+Link::Link(const int jt, const Real it, const Real id, const Real ia, const Real ial,
+           const Real it_min, const Real it_max, const Real it_off, const Real mass, 
+	   const Real cmx, const Real cmy, const Real cmz, const Real ixx, const Real ixy, 
+	   const Real ixz, const Real iyy, const Real iyz, const Real izz, const Real iIm, 
+	   const Real iGr, const Real iB, const Real iCf, const bool dh, 
+	   const bool min_inertial_parameters):
+      R(3,3),
+      qp(0),
+      qpp(0),
+      joint_type(jt),
+      theta(it),
+      d(id),
+      a(ia),
+      alpha(ial),
+      theta_min(it_min),
+      theta_max(it_max),
+      joint_offset(it_off),
+      DH(dh),
+      min_para(min_inertial_parameters),
+      r(),
+      p(3),
+      m(mass),
+      Im(iIm),
+      Gr(iGr),
+      B(iB),
+      Cf(iCf),
+      mc(),
+      I(3,3),
+      immobile(false)
+{
+    if (joint_type == 0)
+	theta += joint_offset;  
+    else
+	d += joint_offset;
+   Real ct, st, ca, sa;
+   ct = cos(theta);
+   st = sin(theta);
+   ca = cos(alpha);
+   sa = sin(alpha);
+
+   qp = qpp = 0.0;
+
+   if (DH)
+   {
+      R(1,1) = ct;
+      R(2,1) = st;
+      R(3,1) = 0.0;
+      R(1,2) = -ca*st;
+      R(2,2) = ca*ct;
+      R(3,2) = sa;
+      R(1,3) = sa*st;
+      R(2,3) = -sa*ct;
+      R(3,3) = ca;
+
+      p(1) = a*ct;
+      p(2) = a*st;
+      p(3) = d;
+   }
+   else     // modified DH notation
+   {
+      R(1,1) = ct;
+      R(2,1) = st*ca;
+      R(3,1) = st*sa;
+      R(1,2) = -st;
+      R(2,2) = ca*ct;
+      R(3,2) = sa*ct;
+      R(1,3) = 0;
+      R(2,3) = -sa;
+      R(3,3) = ca;
+
+      p(1) = a;
+      p(2) = -sa*d;
+      p(3) = ca*d;
+   }
+
+   if (min_para)
+   {
+      mc = ColumnVector(3);
+      mc(1) = cmx;
+      mc(2) = cmy;  // mass * center of gravity
+      mc(3) = cmz;
+   }
+   else
+   {
+      r = ColumnVector(3);
+      r(1) = cmx;   // center of gravity
+      r(2) = cmy;
+      r(3) = cmz;
+   }
+
+   I(1,1) = ixx;
+   I(1,2) = I(2,1) = ixy;
+   I(1,3) = I(3,1) = ixz;
+   I(2,2) = iyy;
+   I(2,3) = I(3,2) = iyz;
+   I(3,3) = izz;
+}
+
+Link::Link(const Link & x)
+//! @brief Copy constructor.
+  : 
+    R(x.R),
+    qp(x.qp),
+    qpp(x.qpp),
+    joint_type(x.joint_type),
+    theta(x.theta),
+    d(x.d),
+    a(x.a),
+    alpha(x.alpha),
+    theta_min(x.theta_min),
+    theta_max(x.theta_max),
+    joint_offset(x.joint_offset),
+    DH(x.DH),
+    min_para(x.min_para),
+    r(x.r),
+    p(x.p),
+    m(x.m),
+    Im(x.Im),
+    Gr(x.Gr),
+    B(x.B),
+    Cf(x.Cf),
+    mc(x.mc),
+    I(x.I),
+    immobile(x.immobile)
+{
+}
+
+Link & Link::operator=(const Link & x)
+//! @brief Overload = operator.
+{
+   joint_type = x.joint_type;
+   theta = x.theta;
+   qp = x.qp;
+   qpp = x.qpp;
+   d = x.d;
+   a = x.a;
+   alpha = x.alpha;
+   theta_min = x.theta_min;
+   theta_max = x.theta_max;
+   joint_offset = x.joint_offset;
+   R = x.R;
+   p = x.p;
+   m = x.m;
+   r = x.r;
+   mc = x.mc;
+   I = x.I;
+   Im = x.Im;
+   Gr = x.Gr;
+   B = x.B;
+   Cf = x.Cf;
+   DH = x.DH;
+   min_para = x.min_para;
+   immobile = x.immobile;
+   return *this;
+}
+
+void Link::transform(const Real q)
+//! @brief Set the rotation matrix R and the vector p.
+{
+   if (DH)
+   {
+      if(joint_type == 0)
+      {
+         Real ct, st, ca, sa;
+				 Real nt=q + joint_offset;
+				 if(theta==nt)
+					 return;
+				 theta=nt;
+         ct = cos(theta);
+         st = sin(theta);
+         ca = R(3,3);
+         sa = R(3,2);
+
+         R(1,1) = ct;
+         R(2,1) = st;
+         R(1,2) = -ca*st;
+         R(2,2) = ca*ct;
+         R(1,3) = sa*st;
+         R(2,3) = -sa*ct;
+         p(1) = a*ct;
+         p(2) = a*st;
+      }
+      else // prismatic joint
+         p(3) = d = q + joint_offset;
+   }
+   else  // modified DH notation
+   {
+      Real ca, sa;
+      ca = R(3,3);
+      sa = -R(2,3);
+      if(joint_type == 0)
+      {
+         Real ct, st;
+				 Real nt=q + joint_offset;
+				 if(theta==nt)
+					 return;
+				 theta=nt;
+         ct = cos(theta);
+         st = sin(theta);
+
+         R(1,1) = ct;
+         R(2,1) = st*ca;
+         R(3,1) = st*sa;
+         R(1,2) = -st;
+         R(2,2) = ca*ct;
+         R(3,2) = sa*ct;
+         R(1,3) = 0;
+      }
+      else
+      {
+         d = q + joint_offset;
+         p(2) = -sa*d;
+         p(3) = ca*d;
+      }
+   }
+}
+
+Real Link::get_q(void) const 
+/*!
+  @brief Return joint position (theta if joint type is rotoide, d otherwise).
+
+  The joint offset is removed from the value.
+*/
+{
+    if(joint_type == 0) 
+	return theta - joint_offset;
+      else 
+	  return d - joint_offset;
+}
+
+
+void Link::set_r(const ColumnVector & r_)
+//! @brief Set the center of gravity position.
+{
+   if(r_.Nrows() == 3)
+      r = r_;
+   else
+      cerr << "Link::set_r: wrong size in input vector." << endl;
+}
+
+void Link::set_mc(const ColumnVector & mc_)
+//! @brief Set the mass \f$\times\f$ center of gravity position.
+{
+   if(mc_.Nrows() == 3)
+      mc = mc_;
+   else
+      cerr << "Link::set_mc: wrong size in input vector." << endl;
+}
+
+/*!
+  @fn void Link::set_I(const Matrix & I)
+  @brief Set the inertia matrix.
+*/
+void Link::set_I(const Matrix & I_)
+{
+   if( (I_.Nrows() == 3) && (I_.Ncols() == 3) )
+      I = I_;
+   else
+      cerr << "Link::set_r: wrong size in input vector." << endl;
+}
+
+Robot_basic::Robot_basic(const Matrix & dhinit, const bool dh_parameter, 
+			 const bool min_inertial_para)
+/*!
+  @brief Constructor.
+  @param dhinit: Robot initialization matrix.
+  @param dh_parameter: true if DH notation, false if modified DH notation.
+  @param min_inertial_para: true inertial parameter are in minimal form.
+
+  Allocate memory for vectors and matrix pointers. Initialize all the Links
+  instance. 
+*/
+  : w(NULL), wp(NULL), vp(NULL), a(NULL), f(NULL), f_nv(NULL), n(NULL), n_nv(NULL),
+  F(NULL), N(NULL), p(NULL), pp(NULL), dw(NULL), dwp(NULL), dvp(NULL), da(NULL),
+  df(NULL), dn(NULL), dF(NULL), dN(NULL), dp(NULL), z0(3), gravity(3), R(NULL),
+  links(NULL), robotType(DEFAULT), dof(0), fix(0)
+{
+   int ndof=0, i;
+
+   gravity = 0.0;
+   gravity(3) = 9.81;
+   z0(1) = z0(2) = 0.0; z0(3) = 1.0;
+   fix = 0;
+   for(i = 1; i <= dhinit.Nrows(); i++)
+      if(dhinit(i,1) == 2)
+      {
+         if (i == dhinit.Nrows())
+            fix = 1;
+         else
+            error("Fix link can only be on the last one");
+      }
+      else
+         ndof++;
+
+   if(ndof < 1)
+      error("Number of degree of freedom must be greater or equal to 1");
+
+   dof = ndof;
+
+   try
+   {
+      links = new Link[dof+fix];
+      links = links-1;
+      w    = new ColumnVector[dof+1];
+      wp   = new ColumnVector[dof+1];
+      vp   = new ColumnVector[dof+fix+1];
+      a    = new ColumnVector[dof+1];
+      f    = new ColumnVector[dof+1];
+      f_nv = new ColumnVector[dof+1];
+      n    = new ColumnVector[dof+1];
+      n_nv = new ColumnVector[dof+1];
+      F    = new ColumnVector[dof+1];
+      N    = new ColumnVector[dof+1];
+      p    = new ColumnVector[dof+fix+1];
+      pp   = new ColumnVector[dof+fix+1];
+      dw   = new ColumnVector[dof+1];
+      dwp  = new ColumnVector[dof+1];
+      dvp  = new ColumnVector[dof+1];
+      da   = new ColumnVector[dof+1];
+      df   = new ColumnVector[dof+1];
+      dn   = new ColumnVector[dof+1];
+      dF   = new ColumnVector[dof+1];
+      dN   = new ColumnVector[dof+1];
+      dp   = new ColumnVector[dof+1];
+      R    = new Matrix[dof+fix+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Robot_basic constructor : new ran out of memory" << endl;
+      exit(1);
+   }
+
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+
+   switch (dhinit.Ncols()){
+   case 5:                  // No inertia, no motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), 0, 0, 0, 0, 0, 0, 0,
+                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dh_parameter, min_inertial_para);
+      }
+      break;
+   case 7:                  // min and max joint angle, no inertia, no motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), dhinit(i,6), dhinit(i,7),
+                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+			 dh_parameter, min_inertial_para);
+      }
+      break;
+   case 15:                // inertia, no motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), 0, 0, 0, dhinit(i,6), dhinit(i,7),
+                         dhinit(i,8), dhinit(i,9), dhinit(i,10), dhinit(i,11),
+                         dhinit(i,12), dhinit(i,13), dhinit(i,14), dhinit(i,15),
+                         0, 0, 0, 0, dh_parameter, min_inertial_para);
+      }
+      break;
+   case 18:                // min and max joint angle, inertia, no motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), dhinit(i,6), dhinit(i,7),
+                         dhinit(i,8), dhinit(i,9), dhinit(i,10), dhinit(i,11),
+                         dhinit(i,12), dhinit(i,13), dhinit(i,14), dhinit(i,15),
+                         dhinit(i,16), dhinit(i,17), dhinit(i,18), 0, 0, 0, 0, 
+			 dh_parameter, min_inertial_para);
+      }
+      break;
+   case 20:                // inertia + motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), 0, 0, dhinit(i,6), dhinit(i,7),
+                         dhinit(i,8), dhinit(i,9), dhinit(i,10), dhinit(i,11),
+                         dhinit(i,12), dhinit(i,13), dhinit(i,14), dhinit(i,15),
+                         dhinit(i,16), dhinit(i,17), dhinit(i,18), dhinit(i,19),
+                         dhinit(i,20), dh_parameter, min_inertial_para);
+      }
+      break;
+   case 22:                // inertia + motor
+      for(i = 1; i <= dof+fix; i++)
+      {
+         links[i] = Link((int) dhinit(i,1), dhinit(i,2), dhinit(i,3),
+                         dhinit(i,4), dhinit(i,5), dhinit(i,6), dhinit(i,7),
+                         dhinit(i,8), dhinit(i,9), dhinit(i,10), dhinit(i,11),
+                         dhinit(i,12), dhinit(i,13), dhinit(i,14), dhinit(i,15),
+                         dhinit(i,16), dhinit(i,17), dhinit(i,18), dhinit(i,19),
+                         dhinit(i,20), dhinit(i,21), dhinit(i,22), 
+			 dh_parameter, min_inertial_para);
+      }
+      break;
+   default:
+      error("Initialisation Matrix does not have 5, ,7, 16 18, 20 or 22 columns.");
+   }
+
+}
+
+Robot_basic::Robot_basic(const Matrix & initrobot, const Matrix & initmotor,
+                         const bool dh_parameter, const bool min_inertial_para)
+/*!
+  @brief Constructor.
+  @param initrobot: Robot initialization matrix.
+  @param initmotor: Motor initialization matrix.
+  @param dh_parameter: true if DH notation, false if modified DH notation.
+  @param min_inertial_para: true inertial parameter are in minimal form.
+
+  Allocate memory for vectors and matrix pointers. Initialize all the Links
+  instance.
+*/
+  : w(NULL), wp(NULL), vp(NULL), a(NULL), f(NULL), f_nv(NULL), n(NULL), n_nv(NULL),
+  F(), N(NULL), p(NULL), pp(NULL), dw(NULL), dwp(NULL), dvp(NULL), da(NULL),
+  df(NULL), dn(NULL), dF(NULL), dN(NULL), dp(NULL), z0(3), gravity(3), R(NULL),
+  links(NULL), robotType(DEFAULT), dof(0), fix(0)
+{
+   int ndof=0, i;
+
+   gravity = 0.0;
+   gravity(3) = 9.81;
+   z0(1) = z0(2) = 0.0; z0(3) = 1.0;
+
+   for(i = 1; i <= initrobot.Nrows(); i++)
+      if(initrobot(i,1) == 2)
+      {
+         if (i == initrobot.Nrows())
+            fix = 1;
+         else
+            error("Fix link can only be on the last one");
+      }
+      else
+         ndof++;
+
+   if(ndof < 1)
+      error("Number of degree of freedom must be greater or equal to 1");
+   dof = ndof;
+
+   try
+   {
+      links = new Link[dof+fix];
+      links = links-1;
+      w    = new ColumnVector[dof+1];
+      wp   = new ColumnVector[dof+1];
+      vp   = new ColumnVector[dof+fix+1];
+      a    = new ColumnVector[dof+1];
+      f    = new ColumnVector[dof+1];
+      f_nv = new ColumnVector[dof+1];
+      n    = new ColumnVector[dof+1];
+      n_nv = new ColumnVector[dof+1];
+      F    = new ColumnVector[dof+1];
+      N    = new ColumnVector[dof+1];
+      p    = new ColumnVector[dof+fix+1];
+      pp   = new ColumnVector[dof+fix+1];
+      dw   = new ColumnVector[dof+1];
+      dwp  = new ColumnVector[dof+1];
+      dvp  = new ColumnVector[dof+1];
+      da   = new ColumnVector[dof+1];
+      df   = new ColumnVector[dof+1];
+      dn   = new ColumnVector[dof+1];
+      dF   = new ColumnVector[dof+1];
+      dN   = new ColumnVector[dof+1];
+      dp   = new ColumnVector[dof+1];
+      R    = new Matrix[dof+fix+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Robot_basic constructor : new ran out of memory" << endl;
+      exit(1);
+   }
+
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+
+   if ( initrobot.Nrows() == initmotor.Nrows() )
+   {
+      if(initmotor.Ncols() == 4)
+      {
+         switch(initrobot.Ncols()){
+         case 15:   // inertia + motor
+            for(i = 1; i <= dof+fix; i++)
+            {
+               links[i] = Link((int) initrobot(i,1), initrobot(i,2), initrobot(i,3),
+                               initrobot(i,4), initrobot(i,5), 0, 0, 0, initrobot(i,6),
+                               initrobot(i,7), initrobot(i,8),  initrobot(i,9),
+                               initrobot(i,10),initrobot(i,11), initrobot(i,12),
+                               initrobot(i,13),initrobot(i,14), initrobot(i,15), 
+			       initmotor(i,1), initmotor(i,2),  initmotor(i,3), 
+			       initmotor(i,4), dh_parameter, min_inertial_para);
+            }
+            break;
+         case 18:    // min and max joint angle, inertia,  motor
+            for(i = 1; i <= dof+fix; i++)
+            {
+               links[i] = Link((int) initrobot(i,1), initrobot(i,2), initrobot(i,3),
+                               initrobot(i,4), initrobot(i,5),  initrobot(i,6),
+                               initrobot(i,7), initrobot(i,8),  initrobot(i,9),
+                               initrobot(i,10),initrobot(i,11), initrobot(i,12),
+                               initrobot(i,13),initrobot(i,14), initrobot(i,15),
+                               initrobot(i,16),initrobot(i,17), initrobot(i,18),
+			       initmotor(i,1), initmotor(i,2), initmotor(i,3),  
+			       initmotor(i,4), dh_parameter, min_inertial_para);
+            }
+            break;
+         default:
+            error("Initialisation robot Matrix does not have 16 or 18 columns.");
+         }
+      }
+      else
+         error("Initialisation robot motor Matrix does not have 4 columns.");
+
+   }
+   else
+      error("Initialisation robot and motor matrix does not have same numbers of Rows.");
+}
+
+Robot_basic::Robot_basic(const int ndof, const bool dh_parameter, 
+                         const bool min_inertial_para)
+/*!
+  @brief Constructor.
+  @param ndof: Robot degree of freedom.
+  @param dh_parameter: true if DH notation, false if modified DH notation.
+  @param min_inertial_para: true inertial parameter are in minimal form.
+
+  Allocate memory for vectors and matrix pointers. Initialize all the Links
+  instance.
+*/
+  : w(NULL), wp(NULL), vp(NULL), a(NULL), f(NULL), f_nv(NULL), n(NULL), n_nv(NULL),
+  F(NULL), N(NULL), p(NULL), pp(NULL), dw(NULL), dwp(NULL), dvp(NULL), da(NULL),
+  df(NULL), dn(NULL), dF(NULL), dN(NULL), dp(NULL), z0(3), gravity(3), R(NULL),
+  links(NULL), robotType(DEFAULT), dof(ndof), fix(0)
+{
+   int i = 0;
+   gravity = 0.0;
+   gravity(3) = 9.81;
+   z0(1) = z0(2) = 0.0; z0(3) = 1.0;
+
+   try
+   {
+      links = new Link[dof];
+      links = links-1;
+      w    = new ColumnVector[dof+1];
+      wp   = new ColumnVector[dof+1];
+      vp   = new ColumnVector[dof+1];
+      a    = new ColumnVector[dof+1];
+      f    = new ColumnVector[dof+1];
+      f_nv = new ColumnVector[dof+1];
+      n    = new ColumnVector[dof+1];
+      n_nv = new ColumnVector[dof+1];
+      F    = new ColumnVector[dof+1];
+      N    = new ColumnVector[dof+1];
+      p    = new ColumnVector[dof+1];
+      pp   = new ColumnVector[dof+fix+1];
+      dw   = new ColumnVector[dof+1];
+      dwp  = new ColumnVector[dof+1];
+      dvp  = new ColumnVector[dof+1];
+      da   = new ColumnVector[dof+1];
+      df   = new ColumnVector[dof+1];
+      dn   = new ColumnVector[dof+1];
+      dF   = new ColumnVector[dof+1];
+      dN   = new ColumnVector[dof+1];
+      dp   = new ColumnVector[dof+1];
+      R    = new Matrix[dof+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Robot_basic constructor : new ran out of memory" << endl;
+      exit(1);
+   }
+
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+}
+
+Robot_basic::Robot_basic(const Robot_basic & x)
+//! @brief Copy constructor.
+  : w(NULL), wp(NULL), vp(NULL), a(NULL), f(NULL), f_nv(NULL), n(NULL), n_nv(NULL),
+  F(NULL), N(NULL), p(NULL), pp(NULL), dw(NULL), dwp(NULL), dvp(NULL), da(NULL),
+  df(NULL), dn(NULL), dF(NULL), dN(NULL), dp(NULL), z0(x.z0), gravity(x.gravity), R(NULL),
+  links(NULL), robotType(x.robotType), dof(x.dof), fix(x.fix)
+{
+   int i = 0;
+
+   try
+   {
+      links = new Link[dof+fix];
+      links = links-1;
+      w    = new ColumnVector[dof+1];
+      wp   = new ColumnVector[dof+1];
+      vp   = new ColumnVector[dof+1];
+      a    = new ColumnVector[dof+1];
+      f    = new ColumnVector[dof+1];
+      f_nv = new ColumnVector[dof+1];
+      n    = new ColumnVector[dof+1];
+      n_nv = new ColumnVector[dof+1];
+      F    = new ColumnVector[dof+1];
+      N    = new ColumnVector[dof+1];
+      p    = new ColumnVector[dof+fix+1];
+      pp   = new ColumnVector[dof+fix+1];
+      dw   = new ColumnVector[dof+1];
+      dwp  = new ColumnVector[dof+1];
+      dvp  = new ColumnVector[dof+1];
+      da   = new ColumnVector[dof+1];
+      df   = new ColumnVector[dof+1];
+      dn   = new ColumnVector[dof+1];
+      dF   = new ColumnVector[dof+1];
+      dN   = new ColumnVector[dof+1];
+      dp   = new ColumnVector[dof+1];
+      R    = new ColumnVector[dof+fix+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Robot_basic constructor : new ran out of memory" << endl;
+      exit(1);
+   }
+
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+
+   for(i = 1; i <= dof+fix; i++)
+      links[i] = x.links[i];
+}
+
+Robot_basic::Robot_basic(const Config& robData, const string & robotName,
+                         const bool dh_parameter, const bool min_inertial_para)
+/*!
+  @brief Constructor.
+  @param robData: Robot configuration file.
+  @param robotName: Basic section name of the configuration file.
+  @param dh_parameter: DH notation (True) or modified DH notation.
+  @param min_inertial_para: Minimum inertial parameters (True).
+
+  Initialize a new robot from a configuration file.
+*/
+  : w(NULL), wp(NULL), vp(NULL), a(NULL), f(NULL), f_nv(NULL), n(NULL), n_nv(NULL),
+  F(NULL), N(NULL), p(NULL), pp(NULL), dw(NULL), dwp(NULL), dvp(NULL), da(NULL),
+  df(NULL), dn(NULL), dF(NULL), dN(NULL), dp(NULL), z0(3), gravity(3), R(NULL),
+  links(NULL), robotType(DEFAULT), dof(0), fix(0)
+{
+   int i = 0;
+   gravity = 0.0;
+   gravity(3) = 9.81;
+   z0(1) = z0(2) = 0.0; z0(3) = 1.0;
+   
+   bool motor;
+
+   if(!robData.select_int(robotName, "dof", dof))
+   {
+      if(dof < 1)
+         error("Robot_basic::Robot_basic: dof is less then one.");
+   }
+   else
+      error("Robot_basic::Robot_basic: error in extracting dof from conf file.");
+
+   if(robData.select_int(robotName, "Fix", fix))
+      fix = 0;
+   if(robData.select_bool(robotName, "Motor", motor))
+      motor = false;
+
+   try
+   {
+      links = new Link[dof+fix];
+      links = links-1;
+      w    = new ColumnVector[dof+1];
+      wp   = new ColumnVector[dof+1];
+      vp   = new ColumnVector[dof+fix+1];
+      a    = new ColumnVector[dof+1];
+      f    = new ColumnVector[dof+1];
+      f_nv = new ColumnVector[dof+1];
+      n    = new ColumnVector[dof+1];
+      n_nv = new ColumnVector[dof+1];
+      F    = new ColumnVector[dof+1];
+      N    = new ColumnVector[dof+1];
+      p    = new ColumnVector[dof+fix+1];
+      pp   = new ColumnVector[dof+fix+1];
+      dw   = new ColumnVector[dof+1];
+      dwp  = new ColumnVector[dof+1];
+      dvp  = new ColumnVector[dof+1];
+      da   = new ColumnVector[dof+1];
+      df   = new ColumnVector[dof+1];
+      dn   = new ColumnVector[dof+1];
+      dF   = new ColumnVector[dof+1];
+      dN   = new ColumnVector[dof+1];
+      dp   = new ColumnVector[dof+1];
+      R    = new Matrix[dof+fix+1];
+   }
+   catch(bad_alloc exception)
+   {
+      cerr << "Robot_basic constructor : new ran out of memory" << endl;
+      exit(1);
+   }
+
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+
+   for(int j = 1; j <= dof+fix; j++)
+   {
+      int joint_type =0;
+      double theta=0, d=0, a=0, alpha=0, theta_min=0, theta_max=0, joint_offset=0,
+         m=0, cx=0, cy=0, cz=0, Ixx=0, Ixy=0, Ixz=0, Iyy=0, Iyz=0, Izz=0,
+         Im=0, Gr=0, B=0, Cf=0;
+      bool immobile=false;
+
+      string robotName_link;
+#ifdef __WATCOMC__
+      ostrstream ostr;
+      {
+         char temp[256];
+         sprintf(temp,"_LINK%d",j);
+         robotName_link = robotName;
+         robotName_link.append(temp);
+      }
+#else
+      ostringstream ostr;
+      ostr << robotName << "_LINK" << j;
+      robotName_link = ostr.str();
+#endif
+
+      robData.select_int(robotName_link, "joint_type", joint_type);
+      robData.select_double(robotName_link, "theta", theta);
+      robData.select_double(robotName_link, "d", d);
+      robData.select_double(robotName_link, "a", a);
+      robData.select_double(robotName_link, "alpha", alpha);
+      robData.select_double(robotName_link, "theta_max", theta_max);
+      robData.select_double(robotName_link, "theta_min", theta_min);
+			if(robData.parameter_exists(robotName_link, "joint_offset"))
+				robData.select_double(robotName_link, "joint_offset", joint_offset);
+			else if(joint_type==0) {
+				joint_offset=theta;
+				theta=0;
+			} else {
+				joint_offset=d;
+				d=0;
+			}
+      robData.select_double(robotName_link, "m", m);
+      robData.select_double(robotName_link, "cx", cx);
+      robData.select_double(robotName_link, "cy", cy);
+      robData.select_double(robotName_link, "cz", cz);
+      robData.select_double(robotName_link, "Ixx", Ixx);
+      robData.select_double(robotName_link, "Ixy", Ixy);
+      robData.select_double(robotName_link, "Ixz", Ixz);
+      robData.select_double(robotName_link, "Iyy", Iyy);
+      robData.select_double(robotName_link, "Iyz", Iyz);
+      robData.select_double(robotName_link, "Izz", Izz);
+      if(robData.parameter_exists(robotName_link,"immobile"))
+        robData.select_bool(robotName_link,"immobile", immobile);
+
+      if(motor)
+      {
+         robData.select_double(robotName_link, "Im", Im);
+         robData.select_double(robotName_link, "Gr", Gr);
+         robData.select_double(robotName_link, "B", B);
+         robData.select_double(robotName_link, "Cf", Cf);
+      }
+
+      links[j] = Link(joint_type, theta, d, a, alpha, theta_min, theta_max,
+                      joint_offset, m, cx, cy, cz, Ixx, Ixy, Ixz, Iyy, Iyz, 
+		      Izz, Im, Gr, B, Cf, dh_parameter, min_inertial_para);
+      links[j].set_immobile(immobile);
+   }
+
+   if(fix)
+      links[dof+fix] = Link(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                            0, 0, 0, 0, 0, 0, 0, 0, 0, dh_parameter, min_inertial_para);
+}
+
+Robot_basic::~Robot_basic() 
+/*!
+  @brief Destructor.
+  
+  Free all vectors and matrix memory.
+*/
+{
+   links = links+1;
+   delete []links;
+   delete []R;
+   delete []dp;
+   delete []dN;
+   delete []dF;
+   delete []dn;
+   delete []df;
+   delete []da;
+   delete []dvp;
+   delete []dwp;
+   delete []dw;
+   delete []pp;
+   delete []p;
+   delete []N;
+   delete []F;
+   delete []n_nv;
+   delete []n;
+   delete []f_nv;
+   delete []f;
+   delete []a;
+   delete []vp;
+   delete []wp;
+   delete []w;
+}
+
+Robot_basic & Robot_basic::operator=(const Robot_basic & x)
+//! @brief Overload = operator.
+{
+   int i = 0;
+   if ( (dof != x.dof) || (fix != x.fix) )
+   {
+      links = links+1;
+      delete []links;
+      delete []R;
+      delete []dp;
+      delete []dN;
+      delete []dF;
+      delete []dn;
+      delete []df;
+      delete []da;
+      delete []dvp;
+      delete []dwp;
+      delete []dw;
+      delete []pp;
+      delete []p;
+      delete []N;
+      delete []F;
+      delete []n_nv;
+      delete []n;
+      delete []f_nv;
+      delete []f;
+      delete []a;
+      delete []vp;
+      delete []wp;
+      delete []w;
+      dof = x.dof;
+      fix = x.fix;
+      gravity = x.gravity;
+      z0 = x.z0;
+
+      try
+      {
+         links = new Link[dof+fix];
+         links = links-1;
+         w     = new ColumnVector[dof+1];
+         wp    = new ColumnVector[dof+1];
+         vp    = new ColumnVector[dof+fix+1];
+         a     = new ColumnVector[dof+1];
+         f     = new ColumnVector[dof+1];
+         f_nv  = new ColumnVector[dof+1];
+         n     = new ColumnVector[dof+1];
+         n_nv  = new ColumnVector[dof+1];
+         F     = new ColumnVector[dof+1];
+         N     = new ColumnVector[dof+1];
+         p     = new ColumnVector[dof+fix+1];
+         pp   = new ColumnVector[dof+fix+1];
+         dw    = new ColumnVector[dof+1];
+         dwp   = new ColumnVector[dof+1];
+         dvp   = new ColumnVector[dof+1];
+         da    = new ColumnVector[dof+1];
+         df    = new ColumnVector[dof+1];
+         dn    = new ColumnVector[dof+1];
+         dF    = new ColumnVector[dof+1];
+         dN    = new ColumnVector[dof+1];
+         dp    = new ColumnVector[dof+1];
+         R     = new Matrix[dof+fix+1];
+      }
+      catch(bad_alloc exception)
+      {
+         cerr << "Robot_basic::operator= : new ran out of memory" << endl;
+         exit(1);
+      }
+   }
+   for(i = 0; i <= dof; i++)
+   {
+      w[i] = ColumnVector(3);
+      w[i] = 0.0;
+      wp[i] = ColumnVector(3);
+      wp[i] = 0.0;
+      vp[i] = ColumnVector(3);
+      dw[i] = ColumnVector(3);
+      dw[i] = 0.0;
+      dwp[i] = ColumnVector(3);
+      dwp[i] = 0.0;
+      dvp[i] = ColumnVector(3);
+      dvp[i] = 0.0;
+   }
+   for(i = 0; i <= dof+fix; i++)
+   {
+      R[i] = Matrix(3,3);
+      R[i] << threebythreeident;
+      p[i] = ColumnVector(3);
+      p[i] = 0.0;
+      pp[i] = p[i];
+   }
+   for(i = 1; i <= dof+fix; i++)
+      links[i] = x.links[i];
+   
+   robotType = x.robotType;
+
+   return *this;
+}
+
+void Robot_basic::error(const string & msg1) const
+//! @brief Print the message msg1 on the console.
+{
+   cerr << endl << "Robot error: " << msg1.c_str() << endl;
+   //   exit(1);
+}
+
+int Robot_basic::get_available_dof(const int endlink)const
+//! @brief Counts number of currently non-immobile links up to and including @a endlink
+{
+  int ans=0;
+  for(int i=1; i<=endlink; i++)
+    if(!links[i].immobile)
+      ans++;
+  return ans;
+}
+
+ReturnMatrix Robot_basic::get_q(void)const
+//! @brief Return the joint position vector.
+{
+   ColumnVector q(dof);
+
+   for(int i = 1; i <= dof; i++)
+      q(i) = links[i].get_q();
+   q.Release(); return q;
+}
+
+ReturnMatrix Robot_basic::get_qp(void)const
+//! @brief Return the joint velocity vector.
+{
+   ColumnVector qp(dof);
+
+   for(int i = 1; i <= dof; i++)
+      qp(i) = links[i].qp;
+   qp.Release(); return qp;
+}
+
+ReturnMatrix Robot_basic::get_qpp(void)const
+//! @brief Return the joint acceleration vector.
+{
+   ColumnVector qpp(dof);
+
+   for(int i = 1; i <= dof; i++)
+      qpp(i) = links[i].qpp;
+   qpp.Release(); return qpp;
+}
+
+ReturnMatrix Robot_basic::get_available_q(const int endlink)const
+//! @brief Return the joint position vector of available (non-immobile) joints up to and including @a endlink.
+{
+   ColumnVector q(get_available_dof(endlink));
+
+   int j=1;
+   for(int i = 1; i <= endlink; i++)
+      if(!links[i].immobile)
+         q(j++) = links[i].get_q();
+   q.Release(); return q;
+}
+
+ReturnMatrix Robot_basic::get_available_qp(const int endlink)const
+//! @brief Return the joint velocity vector of available (non-immobile) joints up to and including @a endlink.
+{
+   ColumnVector qp(get_available_dof(endlink));
+
+   int j=1;
+   for(int i = 1; i <= endlink; i++)
+      if(!links[i].immobile)
+         qp(j++) = links[i].qp;
+   qp.Release(); return qp;
+}
+
+ReturnMatrix Robot_basic::get_available_qpp(const int endlink)const
+//! @brief Return the joint acceleration vector of available (non-immobile) joints up to and including @a endlink.
+{
+   ColumnVector qpp(get_available_dof(endlink));
+
+   int j=1;
+   for(int i = 1; i <= endlink; i++)
+      if(!links[i].immobile)
+         qpp(j) = links[i].qpp;
+   qpp.Release(); return qpp;
+}
+
+void Robot_basic::set_q(const Matrix & q)
+/*!
+  @brief Set the joint position vector.
+
+  Set the joint position vector and recalculate the 
+  orientation matrix R and the position vector p (see 
+  Link class). Print an error if the size of q is incorrect.
+*/
+{
+   int adof=get_available_dof();
+   if(q.Nrows() == dof && q.Ncols() == 1) {
+      for(int i = 1; i <= dof; i++)
+      {
+         links[i].transform(q(i,1));
+         if(links[1].DH)
+         {
+            p[i](1) = links[i].get_a();
+            p[i](2) = links[i].get_d() * links[i].R(3,2);
+            p[i](3) = links[i].get_d() * links[i].R(3,3);
+         }
+         else
+            p[i] = links[i].p;
+      }
+   } else if(q.Nrows() == 1 && q.Ncols() == dof) {
+      for(int i = 1; i <= dof; i++)
+      {
+         links[i].transform(q(1,i));
+         if(links[1].DH)
+         {
+            p[i](1) = links[i].get_a();
+            p[i](2) = links[i].get_d() * links[i].R(3,2);
+            p[i](3) = links[i].get_d() * links[i].R(3,3);
+         }
+         else
+            p[i] = links[i].p;
+      }
+   } else if(q.Nrows() == adof && q.Ncols() == 1) {
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+         if(!links[i].immobile) {
+            links[i].transform(q(j++,1));
+            if(links[1].DH)
+            {
+               p[i](1) = links[i].get_a();
+               p[i](2) = links[i].get_d() * links[i].R(3,2);
+               p[i](3) = links[i].get_d() * links[i].R(3,3);
+            }
+            else
+               p[i] = links[i].p;
+         }
+   } else if(q.Nrows() == 1 && q.Ncols() == adof) {
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+         if(!links[i].immobile) {
+            links[i].transform(q(1,j++));
+            if(links[1].DH)
+            {
+               p[i](1) = links[i].get_a();
+               p[i](2) = links[i].get_d() * links[i].R(3,2);
+               p[i](3) = links[i].get_d() * links[i].R(3,3);
+            }
+            else
+               p[i] = links[i].p;
+         }
+   } else error("q has the wrong dimension in set_q()");
+}
+
+void Robot_basic::set_q(const ColumnVector & q)
+/*!
+  @brief Set the joint position vector.
+
+  Set the joint position vector and recalculate the 
+  orientation matrix R and the position vector p (see 
+  Link class). Print an error if the size of q is incorrect.
+*/
+{
+   if(q.Nrows() == dof) {
+      for(int i = 1; i <= dof; i++)
+      {
+         links[i].transform(q(i));
+         if(links[1].DH)
+         {
+            p[i](1) = links[i].get_a();
+            p[i](2) = links[i].get_d() * links[i].R(3,2);
+            p[i](3) = links[i].get_d() * links[i].R(3,3);
+         }
+         else
+            p[i] = links[i].p;
+      }
+   } else if(q.Nrows() == get_available_dof()) {
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+         if(!links[i].immobile) {
+            links[i].transform(q(j++));
+            if(links[1].DH)
+            {
+               p[i](1) = links[i].get_a();
+               p[i](2) = links[i].get_d() * links[i].R(3,2);
+               p[i](3) = links[i].get_d() * links[i].R(3,3);
+            }
+            else
+               p[i] = links[i].p;
+         }
+   } else error("q has the wrong dimension in set_q()");
+}
+
+void Robot_basic::set_qp(const ColumnVector & qp)
+//! @brief Set the joint velocity vector.
+{
+   if(qp.Nrows() == dof)
+      for(int i = 1; i <= dof; i++)
+         links[i].qp = qp(i);
+   else if(qp.Nrows() == get_available_dof()) {
+      int j=1;
+      for(int i = 1; i <= dof; i++)
+         if(!links[i].immobile)
+            links[i].qp = qp(j++);
+   } else
+      error("qp has the wrong dimension in set_qp()");
+}
+
+void Robot_basic::set_qpp(const ColumnVector & qpp)
+//! @brief Set the joint acceleration vector.
+{
+   if(qpp.Nrows() == dof)
+      for(int i = 1; i <= dof; i++)
+         links[i].qpp = qpp(i);
+   else
+      error("qpp has the wrong dimension in set_qpp()");
+}
+
+/*!
+  @fn Robot::Robot(const int ndof)
+  @brief Constructor
+*/
+Robot::Robot(const int ndof): Robot_basic(ndof, true, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn Robot::Robot(const Matrix & dhinit)
+  @brief Constructor
+*/
+Robot::Robot(const Matrix & dhinit): Robot_basic(dhinit, true, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn Robot::Robot(const Matrix & initrobot, const Matrix & initmotor)
+  @brief Constructor
+*/
+Robot::Robot(const Matrix & initrobot, const Matrix & initmotor):
+      Robot_basic(initrobot, initmotor, true, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn Robot::Robot(const string & filename, const string & robotName)
+  @brief Constructor
+*/
+Robot::Robot(const string & filename, const string & robotName):
+      Robot_basic(Config(filename,true), robotName, true, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn Robot::Robot(const string & robData, const string & robotName)
+  @brief Constructor
+*/
+Robot::Robot(const Config & robData, const string & robotName):
+      Robot_basic(robData, robotName, true, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn Robot::Robot(const Robot & x)
+  @brief Copy constructor
+*/
+Robot::Robot(const Robot & x) : Robot_basic(x)
+{
+}
+
+Robot & Robot::operator=(const Robot & x)
+//! @brief Overload = operator.
+{
+   Robot_basic::operator=(x);
+   return *this;
+}
+
+void Robot::robotType_inv_kin()
+/*!
+  @brief Identify inverse kinematics familly.
+
+  Identify the inverse kinematics analytic solution
+  based on the similarity of the robot DH parameters and
+  the DH parameters of know robots (ex: Puma, Rhino, ...). 
+  The inverse kinematics will be based on a numerical
+  alogorithm if there is no match .
+*/
+{
+	if ( Puma_DH(this))
+		robotType = PUMA;
+	else if ( Rhino_DH(this))
+		robotType = RHINO;
+	else if ( ERS_Leg_DH(this))
+		robotType = ERS_LEG;
+	else if ( ERS2xx_Head_DH(this))
+		robotType = ERS2XX_HEAD;
+	else if ( ERS7_Head_DH(this))
+		robotType = ERS7_HEAD;
+	else
+		robotType = DEFAULT;
+}
+
+// ----------------- M O D I F I E D  D H  N O T A T I O N -------------------
+
+/*!
+  @fn mRobot::mRobot(const int ndof)
+  @brief Constructor.
+*/
+mRobot::mRobot(const int ndof) : Robot_basic(ndof, false, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot::mRobot(const Matrix & dhinit)
+  @brief Constructor.
+*/
+mRobot::mRobot(const Matrix & dhinit) : Robot_basic(dhinit, false, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot::mRobot(const Matrix & initrobot, const Matrix & initmotor)
+  @brief Constructor.
+*/
+mRobot::mRobot(const Matrix & initrobot, const Matrix & initmotor) :
+    Robot_basic(initrobot, initmotor, false, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot::mRobot(const string & filename, const string & robotName)
+  @brief Constructor.
+*/
+mRobot::mRobot(const string & filename, const string & robotName):
+      Robot_basic(Config(filename,true), robotName, false, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot::mRobot(const string & robData, const string & robotName)
+  @brief Constructor.
+*/
+mRobot::mRobot(const Config & robData, const string & robotName):
+      Robot_basic(robData, robotName, false, false)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot::mRobot(const mRobot & x)
+  @brief Copy constructor.
+*/
+mRobot::mRobot(const mRobot & x) : Robot_basic(x)
+{
+    robotType_inv_kin();
+}
+
+mRobot & mRobot::operator=(const mRobot & x)
+//! @brief Overload = operator.
+{
+   Robot_basic::operator=(x);
+   return *this;
+}
+
+void mRobot::robotType_inv_kin()
+/*!
+  @brief Identify inverse kinematics familly.
+
+  Identify the inverse kinematics analytic solution
+  based on the similarity of the robot DH parameters and
+  the DH parameters of know robots (ex: Puma, Rhino, ...). 
+  The inverse kinematics will be based on a numerical
+  alogorithm if there is no match .
+*/
+{
+	if ( Puma_mDH(this))
+		robotType = PUMA;
+	else if ( Rhino_mDH(this))
+		robotType = RHINO;
+	else
+		robotType = DEFAULT;
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const int ndof)
+  @brief Constructor.
+*/
+mRobot_min_para::mRobot_min_para(const int ndof) : Robot_basic(ndof, false, true)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const Matrix & dhinit)
+  @brief Constructor.
+*/
+mRobot_min_para::mRobot_min_para(const Matrix & dhinit):
+      Robot_basic(dhinit, false, true)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const Matrix & initrobot, const Matrix & initmotor)
+  @brief Constructor.
+*/
+mRobot_min_para::mRobot_min_para(const Matrix & initrobot, const Matrix & initmotor) :
+      Robot_basic(initrobot, initmotor, false, true)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const mRobot_min_para & x)
+  @brief Copy constructor
+*/
+mRobot_min_para::mRobot_min_para(const mRobot_min_para & x) : Robot_basic(x)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const string & filename, const string & robotName)
+  @brief Constructor.
+*/
+mRobot_min_para::mRobot_min_para(const string & filename, const string & robotName):
+      Robot_basic(Config(filename,true), robotName, false, true)
+{
+    robotType_inv_kin();
+}
+
+/*!
+  @fn mRobot_min_para::mRobot_min_para(const string & robData, const string & robotName)
+  @brief Constructor.
+*/
+mRobot_min_para::mRobot_min_para(const Config & robData, const string & robotName):
+      Robot_basic(robData, robotName, false, true)
+{
+    robotType_inv_kin();
+}
+
+mRobot_min_para & mRobot_min_para::operator=(const mRobot_min_para & x)
+//! @brief Overload = operator.
+{
+   Robot_basic::operator=(x);
+   return *this;
+}
+
+void mRobot_min_para::robotType_inv_kin()
+/*!
+  @brief Identify inverse kinematics familly.
+
+  Identify the inverse kinematics analytic solution
+  based on the similarity of the robot DH parameters and
+  the DH parameters of know robots (ex: Puma, Rhino, ...). 
+  The inverse kinematics will be based on a numerical
+  alogorithm if there is no match .
+*/
+{
+	if ( Puma_mDH(this))
+		robotType = PUMA;
+	else if ( Rhino_mDH(this))
+		robotType = RHINO;
+	else
+		robotType = DEFAULT;
+}
+
+// ---------------------- Non Member Functions -------------------------------
+
+void perturb_robot(Robot_basic & robot, const double f)
+/*!
+  @brief  Modify a robot.
+  @param robot: Robot_basic reference.
+  @param f: Percentage of erreur between 0 and 1.
+
+  f represents an error to added on the robot inertial parameter.
+  f is between 0 (no error) and 1 (100% error).
+*/
+{
+   if( (f < 0) || (f > 1) )
+      cerr << "perturb_robot: f is not between 0 and 1" << endl;
+
+   double fact;
+   srand(clock());
+   for(int i = 1; i <= robot.get_dof()+robot.get_fix(); i++)
+   {
+      fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      robot.links[i].set_Im(robot.links[i].get_Im()*fact);
+      fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      robot.links[i].set_B(robot.links[i].get_B()*fact);
+      fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      robot.links[i].set_Cf(robot.links[i].get_Cf()*fact);
+      fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      robot.links[i].set_m(robot.links[i].get_m()*fact);
+      //    fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      //    robot.links[i].mc = robot.links[i].mc*fact;
+      fact = (2.0*rand()/RAND_MAX - 1)*f + 1;
+      Matrix I = robot.links[i].get_I()*fact;
+      robot.links[i].set_I(I);
+   }
+}
+
+bool Puma_DH(const Robot_basic *robot)
+/*!
+  @brief  Return true if the robot is like a Puma on DH notation.
+
+  Compare the robot DH table with the Puma DH table. The function 
+  return true if the tables are similar (same alpha and similar a 
+  and d parameters).
+*/
+{
+    if (robot->get_dof() == 6) 
+    {
+	double a[7], d[7], alpha[7];
+	for (int j = 1; j <= 6; j++)      
+	{
+	    if (robot->links[j].get_joint_type())  // All joints are rotoide
+		return false;
+	    a[j] = robot->links[j].get_a();
+	    d[j] = robot->links[j].get_d();
+	    alpha[j] = robot->links[j].get_alpha();
+	}
+
+// comparaison pour alpha de 90 a faire.
+	if( !a[1] && !a[4] && !a[5] && !a[6] && !d[1] && !d[5] && 
+	    !alpha[2] && !alpha[6] && (a[2]>=0) && (a[3]>=0) && (d[2]+d[3]>=0) 
+	    && (d[4]>=0) && (d[6]>=0) )
+	{
+	    return true;
+	}
+
+    }
+
+    return false;
+}
+
+bool Rhino_DH(const Robot_basic *robot)
+/*!
+  @brief  Return true if the robot is like a Rhino on DH notation.
+
+  Compare the robot DH table with the Puma DH table. The function 
+  return true if the tables are similar (same alpha and similar a 
+  and d parameters).
+*/
+{
+    if (robot->get_dof() == 5)
+    {
+	double a[6], d[6], alpha[6];
+	for (int j = 1; j <= 5; j++)      
+	{
+	    if (robot->links[j].get_joint_type())  // All joints are rotoide
+		return false;
+	    a[j] = robot->links[j].get_a();
+	    d[j] = robot->links[j].get_d();
+	    alpha[j] = robot->links[j].get_alpha();
+	}
+
+	if ( !a[1] && !a[5] && !d[2] && !d[3] && !d[4] &&
+	     !alpha[2] && !alpha[3] && !alpha[5] &&
+	     (a[2]>=0) && (a[3]>=0) && (a[4]>=0) && (d[1]>=0) && (d[5]>=0) )
+	{
+	    return true;
+	}
+
+    }
+    
+    return false;
+}
+
+bool ERS_Leg_DH(const Robot_basic *robot)
+/*! @brief  Return true if the robot is like the leg chain of an AIBO on DH notation. */
+{
+	if(robot->get_dof()==5) {
+		Real alpha[6], theta[6];
+		for(unsigned int i=1; i<=5; i++) {
+			if(robot->links[i].get_joint_type()!=0)
+				return false;
+			alpha[i]=robot->links[i].get_alpha();
+			theta[i]=robot->links[i].get_theta();
+		}
+		return (theta[1]==0 && alpha[1]!=0 && theta[2]!=0 && alpha[2]!=0 && theta[3]==0 && alpha[3]!=0);
+	}
+	return false;
+}
+
+bool ERS2xx_Head_DH(const Robot_basic *robot)
+/*! @brief  Return true if the robot is like the camera chain of a 200 series AIBO on DH notation. */
+{
+	if(robot->get_dof()==5) {
+		Real alpha[6], theta[6];
+		bool revolute[6];
+		for(unsigned int i=1; i<=5; i++) {
+			alpha[i]=robot->links[i].get_alpha();
+			theta[i]=robot->links[i].get_theta();
+			revolute[i]=robot->links[i].get_joint_type()==0;
+		}
+		return (theta[1]==0 && alpha[1]!=0 &&
+		        theta[2]==0 && alpha[2]!=0 && revolute[2] &&
+		        theta[3]!=0 && alpha[3]!=0 && revolute[3] &&
+		        revolute[4]);
+	}
+	return false;
+}
+
+bool ERS7_Head_DH(const Robot_basic *robot)
+/*! @brief  Return true if the robot is like the camera or mouth chain of a 7 model AIBO on DH notation. */
+{
+	if(robot->get_dof()==5 || robot->get_dof()==6) {
+		Real alpha[6], theta[6];
+		bool revolute[6];
+		for(unsigned int i=1; i<=5; i++) {
+			alpha[i]=robot->links[i].get_alpha();
+			theta[i]=robot->links[i].get_theta();
+			revolute[i]=robot->links[i].get_joint_type()==0;
+		}
+		return (theta[1]==0 && alpha[1]!=0 &&
+		        theta[2]==0 && alpha[2]!=0 && revolute[2] &&
+		        theta[3]==0 && alpha[3]!=0 && revolute[3] &&
+		        revolute[4]);
+	}
+	return false;
+}
+
+
+bool Puma_mDH(const Robot_basic *robot)
+/*!
+  @brief  Return true if the robot is like a Puma on modified DH notation.
+
+  Compare the robot DH table with the Puma DH table. The function 
+  return true if the tables are similar (same alpha and similar a 
+  and d parameters).
+*/
+{
+    if (robot->get_dof() == 6) 
+    {
+	double a[7], d[7], alpha[7];
+	for (int j = 1; j <= 6; j++)      
+	{
+	    if (robot->links[j].get_joint_type())  // All joints are rotoide
+		return false;
+	    a[j] = robot->links[j].get_a();
+	    d[j] = robot->links[j].get_d();
+	    alpha[j] = robot->links[j].get_alpha();
+	}
+
+// comparaison pour alpha de 90.
+
+	if ( !a[1] && !a[2] && !a[5] && !a[6] && !d[1] && !d[5] &&
+	     !alpha[1] && !alpha[3] && (a[3] >= 0) && (a[4] >= 0) && 
+	     (d[2] + d[3] >=0) && (d[4]>=0) && (d[6]>=0) ) 
+	{
+	    return true;
+	}
+
+    }
+    return false;
+}
+
+bool Rhino_mDH(const Robot_basic *robot)
+/*!
+  @brief  Return true if the robot is like a Rhino on modified DH notation.
+
+  Compare the robot DH table with the Puma DH table. The function 
+  return true if the tables are similar (same alpha and similar a 
+  and d parameters).
+*/
+{
+    if (robot->get_dof() == 5) 
+    {
+	double a[6], d[6], alpha[6];
+	for (int j = 1; j <= 5; j++)      
+	{
+	    if (robot->links[j].get_joint_type())  // All joints are rotoide
+		return false;
+	    a[j] = robot->links[j].get_a();
+	    d[j] = robot->links[j].get_d();
+	    alpha[j] = robot->links[j].get_alpha();
+	}
+// comparaison pour alpha de 90 a ajouter
+	if ( !a[1] && !a[2] && !d[2] && !d[3] && !d[4] && !alpha[1] && 
+	     !alpha[3] && !alpha[4] && (d[1]>=0) && (a[3]>=0) && 
+	     (a[4]>=0) && (a[5]>=0) && (d[5]>=0) )
+	{
+	    return true;
+	}
+
+    }    
+    return false;
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/robot.h
===================================================================
RCS file: Motion/roboop/robot.h
diff -N Motion/roboop/robot.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/robot.h	11 Oct 2004 22:01:28 -0000	1.18
@@ -0,0 +1,564 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Removed class mlink. DH and modified DH parameters are now included in link.
+   -Created virtual class Robot_basic which is now the base class of Robot and 
+    mRobot.
+   -Removed classes RobotMotor and mRobotMotor. Motors effect are now included
+    in classes Robot and mRobot. Code using the old motor class whould need to 
+    be change by changing RobotMotor by Robot and mRobotMotor by mRobot.
+   -Added classes mRobot_min_para (modified DH parameters) and IO_matrix_file.
+   -Created a new torque member function that allowed to have load on last link
+    (Robot_basic, Robot, mRobot, mRobot_min_para).
+   -Added the following member functions in class Robot_basic:
+     void kine_pd(Matrix & Rot, ColumnVector & pos, ColumnVector & posdot)const;
+     void kine_pd(Matrix & Rot, ColumnVector & pos, ColumnVector & posdot, int j)const;
+     ReturnMatrix kine_pd(void)const;
+     ReturnMatrix kine_pd(int j)const;
+    These functions are like the kine(), but with speed calculation.
+   -Added labels theta_min and theta_max in class Link.
+
+2003/04/29: Etienne Lachance
+   -All gnugrah.cpp definitions are now in gnugraph.h.
+   -The following ColumnVector are now part of class Robot_basic: *dw, *dwp, *dvp, *da, 
+    *df, *dn, *dF, *dN, *dp.
+   -Added functons Robot_basic::jacobian_DLS_inv.
+   -Added z0 in Robot_basic.
+   -Fix kine_pd function.
+
+2003/08/22: Etienne Lachance
+   -Added parameter converge in member function inv_kin.
+
+2004/01/23: Etienne Lachance
+   -Added member function G() (gravity torque), and H() (corriolis torque)
+    on all robot class.
+   -Commun definitions are now in include file utils.h.
+   -Added const in non reference argument for all functions prototypes.
+
+2004/03/01: Etienne Lachance
+   -Added non member function perturb_robot.
+
+2004/03/21: Etienne Lachance
+   -Added the following member functions: get_theta_min, get_theta_max,
+    get_mc, get_r, get_p, get_m, get_Im, get_Gr, get_B, get_Cf, get_I,
+    set_m, set_mc, set_r, set_Im, set_B, set_Cf, set_I.
+
+2004/04/26: Etienne Lachance and Vincent Drolet
+   -Added member functions inv_kin_rhino and inv_kin_puma.
+
+2004/05/21: Etienne Lachance
+   -Added Doxygen comments.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+    -Added joint_offset variable in class Link and Link member functions 
+     get_joint_offset. Idea proposed by Ethan Tira-Thompson.
+
+2004/07/16: Ethan Tira-Thompson
+    -Added Link::immobile flag and accessor functions
+    -Added get_available_q* functions
+    -inv_kin functions are now all virtual
+    -Added parameters to jacobian and inv_kin functions to work with frames
+     other than the end effector
+
+2004/07/21: Ethan Tira-Thompson
+    -Added inv_kin_pos() for times when you only care about position
+    -Added inv_kin_orientation() for times when you only care about orientation
+    -Added dTdqi(...,endlink) variants
+    -Fixed some hidden functions
+    
+2004/09/01: Ethan Tira-Thompson
+    -Added constructor for instantiation from already-read config file.
+     This saves time when having to reconstruct repeatedly with slow disks
+-------------------------------------------------------------------------------
+*/
+
+#ifndef __cplusplus
+#error Must use C++ for the type Robot
+#endif
+#ifndef ROBOT_H
+#define ROBOT_H
+
+/*!
+  @file robot.h
+  @brief Robots class definitions.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_rcsid[] = "$Id: robot.h,v 1.18 2004/10/11 22:01:28 ejt Exp $";
+
+#include "utils.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+/*!
+  @class Link
+  @brief Link definitions.
+
+  A n degree of freedom (dof) serial manipulator is composed of n links. This class
+  describe the property of a link. A n dof robot has n instance of the class Link.
+*/
+class Link  
+{
+    friend class Robot_basic;
+    friend class Robot;
+    friend class mRobot;
+    friend class mRobot_min_para;
+
+public:
+   Link(const int jt = 0, const Real it = 0.0, const Real id = 0.0,
+        const Real ia = 0.0, const Real ial = 0.0, const Real theta_min = -M_PI/2,
+        const Real theta_max = M_PI/2, const Real it_off = 0.0, const Real mass = 1.0,
+        const Real cmx = 0.0, const Real cmy = 0.0, const Real cmz = 0.0,
+        const Real ixx = 0.0, const Real ixy = 0.0, const Real ixz = 0.0,
+        const Real iyy = 0.0, const Real iyz = 0.0, const Real izz = 0.0,
+        const Real iIm = 0.0, const Real iGr = 0.0, const Real iB = 0.0,
+        const Real iCf = 0.0, const bool dh = true, const bool min_inertial_para = false);
+   Link(const Link & x);
+   ~Link(){}                                            //!< Destructor.
+   Link & operator=(const Link & x);
+   void transform(const Real q);
+   bool get_DH(void) const {return DH; }                //!< Return DH value.
+   int get_joint_type(void) const { return joint_type; }//!< Return the joint type.
+   Real get_theta(void) const { return theta; }         //!< Return theta.
+   Real get_d(void) const { return d; }                 //!< Return d.
+   Real get_a(void) const { return a; }                 //!< Return a.
+   Real get_alpha(void) const { return alpha; }         //!< Return alpha.
+   Real get_q(void) const;
+   Real get_theta_min(void) const { return theta_min; } //!< Return theta_min.
+   Real get_theta_max(void) const { return theta_max; } //!< Return theta_max.
+   Real get_joint_offset(void) const { return joint_offset; } //!< Return joint_offset.
+   ReturnMatrix get_mc(void) { return mc; }             //!< Return mc.
+   ReturnMatrix get_r(void) { return r; }               //!< Return r.
+   ReturnMatrix get_p(void) const { return p; }         //!< Return p.
+   Real get_m(void) const { return m; }                 //!< Return m.
+   Real get_Im(void) const { return Im; }               //!< Return Im.
+   Real get_Gr(void) const { return Gr; }               //!< Return Gr.
+   Real get_B(void) const { return B; }                 //!< Return B.
+   Real get_Cf(void) const { return Cf; }               //!< Return Cf.
+   ReturnMatrix get_I(void) const { return I; }         //!< Return I.
+   bool get_immobile(void) const { return immobile; }   //!< Return immobile.
+   void set_m(const Real m_) { m = m_; }                //!< Set m.
+   void set_mc(const ColumnVector & mc_);               //!< Set mc.
+   void set_r(const ColumnVector & r_);                 //!< Set r.
+   void set_Im(const Real Im_) { Im = Im_; }            //!< Set Im.
+   void set_B(const Real B_) { B = B_; }                //!< Set B.
+   void set_Cf(const Real Cf_) { Cf = Cf_; }            //!< Set Cf.
+   void set_I(const Matrix & I);                        //!< Set I.
+   void set_immobile(bool im) { immobile=im; }          //!< Set immobile.
+
+   Matrix R;          //!< Orientation matrix of actual link w.r.t to previous link.
+   Real qp,           //!< Joint velocity.
+        qpp;          //!< Joint acceleration.
+
+private:
+   int joint_type;    //!< Joint type.
+   Real theta,        //!< theta DH parameter.
+        d,            //!< d DH parameter.
+        a,            //!< a DH parameter.
+        alpha,        //!< alpha DH parameter.
+        theta_min,    //!< Min joint angle.
+        theta_max,    //!< Max joint angle. 
+        joint_offset; //!< Offset in joint angle (rotoide and prismatic).
+   bool DH,           //!< DH notation(true) or DH modified notation.
+        min_para;     //!< Minimum inertial parameter.
+   ColumnVector r,    //!< Position of center of mass w.r.t. link coordinate system (min_para=F).
+                p;    //!< Position vector of actual link w.r.t to previous link.
+   Real m,            //!< Mass of the link.
+   Im,                //!< Motor Inertia.
+   Gr,                //!< Gear Ratio.
+   B,                 //!< Viscous coefficient.
+   Cf;                //!< Coulomb fiction coefficient.
+   ColumnVector mc;   //!< Mass \f$\times\f$ center of gravity (used if min_para = true).
+   Matrix I;          //!< Inertia matrix w.r.t. center of mass and link coordinate system orientation.
+   bool immobile;     //!< true if the joint is to be considered locked - ignored for inverse kinematics, but can still be reassigned through transform
+};
+
+/*!
+  @class Robot_basic
+  @brief Virtual base robot class.
+*/
+class Robot_basic {
+   friend class Robot;
+   friend class mRobot;
+   friend class mRobot_min_para;
+   friend class Robotgl;
+   friend class mRobotgl;
+public:
+   explicit Robot_basic(const int ndof = 1, const bool dh_parameter = false,
+               const bool min_inertial_para = false);
+   explicit Robot_basic(const Matrix & initrobot_motor, const bool dh_parameter = false,
+               const bool min_inertial_para = false);
+   explicit Robot_basic(const Matrix & initrobot, const Matrix & initmotor,
+               const bool dh_parameter = false, const bool min_inertial_para = false);
+   explicit Robot_basic(const Config & robData, const string & robotName,
+               const bool dh_parameter = false, const bool min_inertial_para = false);
+   Robot_basic(const Robot_basic & x);
+   virtual ~Robot_basic();
+   Robot_basic & operator=(const Robot_basic & x);
+
+   Real get_q(const int i) const {            //!< Return joint i position.
+      if(i < 1 || i > dof) error("i must be 1 <= i <= dof");
+      return links[i].get_q();
+   }
+   bool get_DH()const { return links[1].DH; } //!< Return true if in DH notation, false otherwise.
+   int get_dof()const { return dof; }         //!< Return dof.
+   int get_available_dof()const { return get_available_dof(dof); } //!<Counts number of currently non-immobile links
+   int get_available_dof(const int endlink)const;
+   int get_fix()const { return fix; }         //!< Return fix.
+   ReturnMatrix get_q(void)const;
+   ReturnMatrix get_qp(void)const;
+   ReturnMatrix get_qpp(void)const;
+   ReturnMatrix get_available_q(void)const { return get_available_q(dof); } //!< Return the joint position vector of available (non-immobile) joints.
+   ReturnMatrix get_available_qp(void)const { return get_available_qp(dof); } //!< Return the joint velocity vector of available (non-immobile) joints.
+   ReturnMatrix get_available_qpp(void)const { return get_available_qpp(dof); } //!< Return the joint acceleration vector of available (non-immobile) joints.
+   ReturnMatrix get_available_q(const int endlink)const;
+   ReturnMatrix get_available_qp(const int endlink)const;
+   ReturnMatrix get_available_qpp(const int endlink)const;
+   void set_q(const ColumnVector & q);
+   void set_q(const Matrix & q);
+   void set_q(const Real q, const int i) {     //!< Set joint i position.
+      if(i < 1 || i > dof) error("i must be 1 <= i <= dof");
+      links[i].transform(q);
+   }
+   void set_qp(const ColumnVector & qp);
+   void set_qpp(const ColumnVector & qpp);
+   void kine(Matrix & Rot, ColumnVector & pos)const;
+   void kine(Matrix & Rot, ColumnVector & pos, const int j)const;
+   ReturnMatrix kine(void)const;
+   ReturnMatrix kine(const int j)const;
+   ReturnMatrix kine_pd(const int ref=0)const;
+   virtual void kine_pd(Matrix & Rot, ColumnVector & pos,
+                        ColumnVector & pos_dot, const int ref)const=0; 
+   virtual void robotType_inv_kin() = 0;
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj = 0);
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, bool & converge) {return inv_kin(Tobj,mj,dof,converge);} //!< Numerical inverse kinematics.  See inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_pos(const ColumnVector & Pobj, const int mj, const int endlink, const ColumnVector& Plink, bool & converge);
+   virtual ReturnMatrix inv_kin_orientation(const Matrix & Robj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_rhino(const Matrix & Tobj, bool & converge) = 0;
+   virtual ReturnMatrix inv_kin_puma(const Matrix & Tobj, bool & converge) = 0;
+   virtual ReturnMatrix jacobian(const int ref=0)const { return jacobian(dof,ref); } //!< Jacobian of mobile links expressed at frame ref. See jacobian(const int endlink, const int reg)
+   virtual ReturnMatrix jacobian(const int endlink, const int ref)const = 0;
+   virtual ReturnMatrix jacobian_dot(const int ref=0)const = 0;
+   ReturnMatrix jacobian_DLS_inv(const double eps, const double lambda_max, const int ref=0)const;
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i) { dTdqi(dRot,dpos,i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual ReturnMatrix dTdqi(const int i) { return dTdqi(i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink) = 0;
+   virtual ReturnMatrix dTdqi(const int i, const int endlink) = 0;
+   ReturnMatrix acceleration(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & tau);
+   ReturnMatrix acceleration(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & tau, const ColumnVector & Fext,
+                             const ColumnVector & Next);
+   ReturnMatrix inertia(const ColumnVector & q);
+   virtual ReturnMatrix torque_novelocity(const ColumnVector & qpp) = 0;
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp) = 0;
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp,
+                               const ColumnVector & Fext_,
+                               const ColumnVector & Next_) = 0;
+   virtual void delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & qpp, const ColumnVector & dq,
+                             const ColumnVector & dqp, const ColumnVector & dqpp,
+                             ColumnVector & torque, ColumnVector & dtorque) =0;
+   virtual void dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                          const ColumnVector & qpp, const ColumnVector & dq,
+                          ColumnVector & torque, ColumnVector & dtorque) =0;
+   virtual void dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & dqp, ColumnVector & torque,
+                           ColumnVector & dtorque) =0;
+   ReturnMatrix dtau_dq(const ColumnVector & q, const ColumnVector & qp,
+                        const ColumnVector & qpp);
+   ReturnMatrix dtau_dqp(const ColumnVector & q, const ColumnVector & qp);
+   virtual ReturnMatrix G() = 0;
+   virtual ReturnMatrix C(const ColumnVector & qp) = 0;
+   void error(const string & msg1) const;
+
+   //! useful for fixing x to be at least min or at most max
+   static Real limit_range(Real x, Real min, Real max) { return x>max?max:(x<min?min:x); }
+
+   //! useful for fixing x to be at least min or at most max; handles angles so closest boundary is picked, but assumes x is normalized (-pi,pi)
+   static Real limit_angle(Real x, Real min, Real max) {
+      if(x<min || x>max) {
+         Real mn_dist=fabs(normalize_angle(min-x));
+         Real mx_dist=fabs(normalize_angle(max-x));
+         if(mn_dist<mx_dist)
+            return min;
+         else
+            return max;
+      } else
+         return x;
+   }
+
+   //! ensures that @a t is in the range (-pi,pi)  (upper boundary may not be inclusive...?)
+   static Real normalize_angle(Real t) { return t-rint(t/(2*M_PI))*(2*M_PI); }
+
+   //! converts a homogenous vector to a normal vector
+   static Real homog_norm(const ColumnVector& v) {
+      Real tot=0;
+      for(int i=1; i<=v.nrows()-1; i++)
+         tot+=v(i)*v(i);
+      return sqrt(tot)/v(v.nrows());
+   }
+   
+   void convertFrame(Matrix& R, ColumnVector& p, int cur, int dest) const;
+   ReturnMatrix convertFrame(int cur, int dest) const;
+	 void convertLinkToFrame(Matrix& R, ColumnVector& p, int cur, int dest) const;
+   ReturnMatrix convertLinkToFrame(int cur, int dest) const;   
+	 void convertFrameToLink(Matrix& R, ColumnVector& p, int cur, int dest) const;
+   ReturnMatrix convertFrameToLink(int cur, int dest) const;   
+   void convertLink(Matrix& R, ColumnVector& p, int cur, int dest) const;
+   ReturnMatrix convertLink(int cur, int dest) const;   
+   
+   ColumnVector *w, *wp, *vp, *a, *f, *f_nv, *n, *n_nv, *F, *N, *p, *pp,
+   *dw, *dwp, *dvp, *da, *df, *dn, *dF, *dN, *dp, 
+       z0,      //!< Axis vector at each joint.
+       gravity; //!< Gravity vector.
+   Matrix *R;   //!< Temprary rotation matrix.
+   Link *links; //!< Pointer on Link cclass.
+
+private:
+   //! enum EnumRobotType
+   enum EnumRobotType 
+   { 
+       DEFAULT = 0,   //!< Default robot familly.
+       RHINO = 1,     //!< Rhino familly.
+       PUMA = 2,      //!< Puma familly.
+       ERS_LEG,       //!< AIBO leg
+       ERS2XX_HEAD,   //!< AIBO 200 series camera chain (210, 220)
+       ERS7_HEAD,     //!< AIBO 7 model camera chain
+   };
+   EnumRobotType robotType; //!< Robot type.
+   int dof,                 //!< Degree of freedom.
+       fix;                 //!< Virtual link, used with modified DH notation.
+
+	 static ReturnMatrix pack4x4(const Matrix& R, const ColumnVector& p) {
+		 Matrix T(4,4);
+		 T.SubMatrix(1,3,1,3)=R;
+		 T.SubMatrix(1,3,4,4)=p;
+		 T(4,1)=0; T(4,2)=0; T(4,3)=0; T(4,4)=1;
+		 T.Release(); return T;
+	 }		 
+};
+
+/*!
+  @class Robot
+  @brief DH notation robot class.
+*/
+class Robot : public Robot_basic
+{
+public:
+   explicit Robot(const int ndof=1);
+   explicit Robot(const Matrix & initrobot);
+   explicit Robot(const Matrix & initrobot, const Matrix & initmotor);
+   Robot(const Robot & x);
+   explicit Robot(const string & filename, const string & robotName);
+   explicit Robot(const Config & robData, const string & robotName);
+   ~Robot(){}   //!< Destructor.
+   Robot & operator=(const Robot & x);
+   virtual void robotType_inv_kin();
+   virtual void kine_pd(Matrix & Rot, ColumnVector & pos,
+                        ColumnVector & pos_dot, const int ref)const;
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj = 0);
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, bool & converge) {return inv_kin(Tobj,mj,dof,converge);} //!< Numerical inverse kinematics.  See inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_pos(const ColumnVector & Pobj, const int mj, const int endlink, const ColumnVector& Plink, bool & converge);
+   virtual ReturnMatrix inv_kin_orientation(const Matrix & Robj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_rhino(const Matrix & Tobj, bool & converge);
+   virtual ReturnMatrix inv_kin_puma(const Matrix & Tobj, bool & converge);
+
+   virtual ReturnMatrix inv_kin_ers_pos(const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool & converge);
+
+   virtual ReturnMatrix jacobian(const int ref=0)const { return jacobian(dof,ref); } //!< Jacobian of mobile links expressed at frame ref.
+   virtual ReturnMatrix jacobian(const int endlink, const int ref)const;
+   virtual ReturnMatrix jacobian_dot(const int ref=0)const;
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i) { dTdqi(dRot,dpos,i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual ReturnMatrix dTdqi(const int i) { return dTdqi(i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink);
+   virtual ReturnMatrix dTdqi(const int i, const int endlink);
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp);
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp,
+                               const ColumnVector & Fext_,
+                               const ColumnVector & Next_);
+   virtual ReturnMatrix torque_novelocity(const ColumnVector & qpp);
+   virtual void delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & qpp, const ColumnVector & dq,
+                             const ColumnVector & dqp, const ColumnVector & dqpp,
+                             ColumnVector & ltorque, ColumnVector & dtorque);
+   virtual void dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                          const ColumnVector & qpp, const ColumnVector & dq,
+                          ColumnVector & torque, ColumnVector & dtorque);
+   virtual void dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & dqp, ColumnVector & torque,
+                           ColumnVector & dtorque);
+   virtual ReturnMatrix G();
+   virtual ReturnMatrix C(const ColumnVector & qp);
+   
+protected:
+   Real computeFirstERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, Real min, Real max, bool & converge);
+   Real computeSecondERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool invert, Real min, Real max, bool & converge);
+   Real computeThirdERSLink(int curlink, const ColumnVector & Pobj, const int endlink, const ColumnVector& Plink, bool invert, Real min, Real max, bool & converge);
+};
+
+// ---------- R O B O T   M O D I F I E D   DH   N O T A T I O N --------------
+
+/*!
+  @class mRobot
+  @brief Modified DH notation robot class.
+*/
+class mRobot : public Robot_basic {
+public:
+   explicit mRobot(const int ndof=1);
+   explicit mRobot(const Matrix & initrobot_motor);
+   explicit mRobot(const Matrix & initrobot, const Matrix & initmotor);
+   mRobot(const mRobot & x);
+   explicit mRobot(const string & filename, const string & robotName);
+   explicit mRobot(const Config & robData, const string & robotName);
+   ~mRobot(){}    //!< Destructor.
+   mRobot & operator=(const mRobot & x);
+   virtual void robotType_inv_kin();
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj = 0);
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, bool & converge) {return inv_kin(Tobj,mj,dof,converge);} //!< Numerical inverse kinematics.  See inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_rhino(const Matrix & Tobj, bool & converge);
+   virtual ReturnMatrix inv_kin_puma(const Matrix & Tobj, bool & converge);
+   virtual void kine_pd(Matrix & Rot, ColumnVector & pos,
+                        ColumnVector & pos_dot, const int ref)const;
+   virtual ReturnMatrix jacobian(const int ref=0)const { return jacobian(dof,ref); } //!< Jacobian of mobile links expressed at frame ref.
+   virtual ReturnMatrix jacobian(const int endlink, const int ref)const;
+   virtual ReturnMatrix jacobian_dot(const int ref=0)const;
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i) { dTdqi(dRot,dpos,i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual ReturnMatrix dTdqi(const int i) { return dTdqi(i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink);
+   virtual ReturnMatrix dTdqi(const int i, const int endlink);
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp);
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp,
+                               const ColumnVector & Fext_,
+                               const ColumnVector & Next_);
+   virtual ReturnMatrix torque_novelocity(const ColumnVector & qpp);
+   virtual void delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & qpp, const ColumnVector & dq,
+                             const ColumnVector & dqp, const ColumnVector & dqpp,
+                             ColumnVector & torque, ColumnVector & dtorque);
+   virtual void dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                          const ColumnVector & qpp, const ColumnVector & dq,
+                          ColumnVector & torque, ColumnVector & dtorque);
+   virtual void dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & dqp, ColumnVector & torque,
+                           ColumnVector & dtorque);
+   virtual ReturnMatrix G();
+   virtual ReturnMatrix C(const ColumnVector & qp);
+};
+
+// --- R O B O T  DH  M O D I F I E D,  M I N I M U M   P A R A M E T E R S ---
+
+/*!
+  @class mRobot_min_para
+  @brief Modified DH notation and minimal inertial parameters robot class.
+*/
+class mRobot_min_para : public Robot_basic 
+{
+public:
+   explicit mRobot_min_para(const int ndof=1);
+   explicit mRobot_min_para(const Matrix & dhinit);
+   explicit mRobot_min_para(const Matrix & initrobot, const Matrix & initmotor);
+   mRobot_min_para(const mRobot_min_para & x);
+   explicit mRobot_min_para(const string & filename, const string & robotName);
+   explicit mRobot_min_para(const Config & robData, const string & robotName);
+   ~mRobot_min_para(){}    //!< Destructor.
+   mRobot_min_para & operator=(const mRobot_min_para & x);
+   virtual void robotType_inv_kin();
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj = 0);
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, bool & converge) {return inv_kin(Tobj,mj,dof,converge);} //!< Numerical inverse kinematics.  See inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge)
+   virtual ReturnMatrix inv_kin(const Matrix & Tobj, const int mj, const int endlink, bool & converge);
+   virtual ReturnMatrix inv_kin_rhino(const Matrix & Tobj, bool & converge);
+   virtual ReturnMatrix inv_kin_puma(const Matrix & Tobj, bool & converge);
+   virtual void kine_pd(Matrix & Rot, ColumnVector & pos,
+                        ColumnVector & pos_dot, const int ref=0)const;
+   virtual ReturnMatrix jacobian(const int ref=0)const { return jacobian(dof,ref); } //!< Jacobian of mobile links expressed at frame ref.
+   virtual ReturnMatrix jacobian(const int endlink, const int ref)const;
+   virtual ReturnMatrix jacobian_dot(const int ref=0)const;
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i) { dTdqi(dRot,dpos,i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual ReturnMatrix dTdqi(const int i) { return dTdqi(i,dof); } //!< Partial derivative of the robot position (homogeneous transf.) See dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink)
+   virtual void dTdqi(Matrix & dRot, ColumnVector & dpos, const int i, const int endlink);
+   virtual ReturnMatrix dTdqi(const int i, const int endlink);
+   virtual ReturnMatrix torque(const ColumnVector & q, const ColumnVector & qp,
+                               const ColumnVector & qpp);
+   virtual ReturnMatrix torque(const ColumnVector & q,
+                               const ColumnVector & qp,
+                               const ColumnVector & qpp,
+                               const ColumnVector & Fext_,
+                               const ColumnVector & Next_);
+   virtual ReturnMatrix torque_novelocity(const ColumnVector & qpp);
+   virtual void delta_torque(const ColumnVector & q, const ColumnVector & qp,
+                             const ColumnVector & qpp, const ColumnVector & dq,
+                             const ColumnVector & dqp, const ColumnVector & dqpp,
+                             ColumnVector & torque, ColumnVector & dtorque);
+   virtual void dq_torque(const ColumnVector & q, const ColumnVector & qp,
+                          const ColumnVector & qpp, const ColumnVector & dq,
+                          ColumnVector & torque, ColumnVector & dtorque);
+   virtual void dqp_torque(const ColumnVector & q, const ColumnVector & qp,
+                           const ColumnVector & dqp, ColumnVector & torque,
+                           ColumnVector & dtorque);
+   virtual ReturnMatrix G();
+   virtual ReturnMatrix C(const ColumnVector & qp);
+};
+
+void perturb_robot(Robot_basic & robot, const double f = 0.1);
+
+bool Puma_DH(const Robot_basic *robot);
+bool Rhino_DH(const Robot_basic *robot);
+bool ERS_Leg_DH(const Robot_basic *robot);
+bool ERS2xx_Head_DH(const Robot_basic *robot);
+bool ERS7_Head_DH(const Robot_basic *robot);
+bool Puma_mDH(const Robot_basic *robot);
+bool Rhino_mDH(const Robot_basic *robot);
+
+#ifdef use_namespace
+}
+#endif
+
+#endif 
+
Index: Motion/roboop/sensitiv.cpp
===================================================================
RCS file: Motion/roboop/sensitiv.cpp
diff -N Motion/roboop/sensitiv.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/sensitiv.cpp	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,114 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+    -Added Doxygen comments.
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file sensitiv.cpp
+  @brief Delta torque (linearized dynamics).
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: sensitiv.cpp,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+ReturnMatrix Robot_basic::dtau_dq(const ColumnVector & q,
+                                  const ColumnVector & qp,
+                                  const ColumnVector & qpp)
+/*!
+  @brief Sensitivity of the dynamics with respect to \f$ q \f$
+
+  This function computes \f$S_2(q, \dot{q}, \ddot{q})\f$.
+*/
+{
+   int i, j;
+   Matrix ldtau_dq(dof,dof);
+   ColumnVector ltorque(dof);
+   ColumnVector dtorque(dof);
+   ColumnVector dq(dof);
+   for(i = 1; i <= dof; i++) {
+      for(j = 1; j <= dof; j++) {
+         dq(j) = (i == j ? 1.0 : 0.0);
+      }
+      dq_torque(q,qp,qpp,dq,ltorque,dtorque);
+      for(j = 1; j <= dof; j++) {
+         ldtau_dq(j,i) = dtorque(j);
+      }
+   }
+   ldtau_dq.Release(); return ldtau_dq;
+}
+
+ReturnMatrix Robot_basic::dtau_dqp(const ColumnVector & q,
+                                   const ColumnVector & qp)
+/*!
+  @brief Sensitivity of the dynamics with respect to \f$\dot{q} \f$
+
+  This function computes \f$S_1(q, \dot{q})\f$.
+*/
+{
+   int i, j;
+   Matrix ldtau_dqp(dof,dof);
+   ColumnVector ltorque(dof);
+   ColumnVector dtorque(dof);
+   ColumnVector dqp(dof);
+   for(i = 1; i <= dof; i++) {
+      for(j = 1; j <= dof; j++) {
+         dqp(j) = (i == j ? 1.0 : 0.0);
+      }
+      dqp_torque(q,qp,dqp,ltorque,dtorque);
+      for(j = 1; j <= dof; j++) {
+         ldtau_dqp(j,i) = dtorque(j);
+      }
+   }
+   ldtau_dqp.Release(); return ldtau_dqp;
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
Index: Motion/roboop/trajectory.cpp
===================================================================
RCS file: Motion/roboop/trajectory.cpp
diff -N Motion/roboop/trajectory.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/trajectory.cpp	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,860 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/06/02: Etienne Lachance
+    -Added class Trajectory_Select.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace.
+-------------------------------------------------------------------------------
+*/
+
+/*! 
+  @file trajectory.cpp
+  @brief Trajectory member functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: trajectory.cpp,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "trajectory.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+Spl_cubic::Spl_cubic(const Matrix & pts)
+/*!
+  @brief Constructor
+  @param pts: Matrix containing the spline data.
+
+  The first line of the Matrix contain the sampling time
+  Second line contain data (sk) to create spline i.
+  Third             "                       "    i+1.
+  on Nth line                                   i+N.
+
+  The spline has the following form:
+  \f[
+    s = A_k(t-t_k)^3 + B_k(t-t_k)^2 + C_k(t-t_k) + D_k
+  \f]
+*/
+{
+   int N = pts.Ncols();
+   bad_data = false;
+   nb_path = pts.Nrows()-1;
+
+   if(!N)
+   {
+      bad_data = true;
+      cerr << "Spl_cubic::Spl_cubic: size of time vector is zero." << endl;
+      return;
+   }
+   if(N <= 3)
+   {
+      bad_data = true;
+      cerr << "Spl_cubic::Spl_cubic: need at least 4 points to produce a cubic spline." << endl;
+      return;
+   }
+   if(!nb_path)
+   {
+      bad_data = true;
+      cerr << "Spl_cubic::Spl_cubic: No data for each points." << endl;
+      return;
+   }
+
+   ColumnVector delta(N-1), beta(N-1);
+   tk = pts.SubMatrix(1,1,1,N);           // time at sampling point
+
+   for(int i = 1; i <= N-1; i++)
+   {
+      delta(i) = pts(1,i+1) - pts(1,i);  // eq 5.58d Angeles
+
+      if(!delta(i))
+      {
+         bad_data = true;
+         cerr << "Spl_cubic::Spl_cubic: time between input points is zero" << endl;
+         return;
+      }
+      beta(i) = 1/delta(i);              // eq 5.58e Angeles
+   }
+
+   Matrix A(N-2, N-2); A = 0;             // eq 5.59 Angeles
+   A(1,1) = 2*(delta(1)+delta(2));
+   A(1,2) = delta(2);
+   for(int j = 2; j <= N-2; j++)
+   {
+      A(j,j-1) = delta(j);
+      A(j,j)   = 2*(delta(j)+delta(j+1));
+      if( (j+1) <= A.Ncols())
+         A(j,j+1) = delta(j+1);
+   }
+
+   Matrix C(N-2, N);   C = 0;             // eq 5.58c Angeles
+   for(int k = 1; k <= N-2; k++)
+   {
+      C(k,k) = beta(k);
+      C(k,k+1) = -(beta(k)+beta(k+1));
+      C(k,k+2) = beta(k+1);
+   }
+
+   Matrix _6AiC = 6*A.i()*C;        // eq 5.58a Angeles
+
+   ColumnVector dd_s(N);   // second spline derivative at sampling points
+   dd_s(1) = dd_s(N) = 0;  // second der is 0 on first and last point of natural splines.
+
+   Ak = Matrix(nb_path, N-1);
+   Bk = Matrix(nb_path, N-1);
+   Ck = Matrix(nb_path, N-1);
+   Dk = Matrix(nb_path, N-1);
+
+   for(int ii = 2; ii <= nb_path+1; ii++)
+   {
+      dd_s.SubMatrix(2,N-1,1,1) = _6AiC*pts.SubMatrix(ii,ii,1,N).t();
+
+      for(int jj = 1; jj < N; jj++)
+      {
+         // eq 5.55a - 5.55d Angeles
+         Ak(ii-1,jj) = 1/(6.0*delta(jj))*(dd_s(jj+1) - dd_s(jj));
+         Bk(ii-1,jj) = 1/2.0*dd_s(jj);
+         Ck(ii-1,jj) = (pts(ii,jj+1)-pts(ii,jj))/delta(jj) -
+                       1/6.0*delta(jj)*(dd_s(jj+1) + 2*dd_s(jj));
+         Dk(ii-1,jj) = pts(ii,jj);
+      }
+   }
+}
+
+Spl_cubic::Spl_cubic(const Spl_cubic & x)
+//!  @brief Copy constructor.
+{
+   bad_data = x.bad_data;
+   nb_path = x.nb_path;
+   Ak = x.Ak;
+   Bk = x.Bk;
+   Ck = x.Ck;
+   Dk = x.Dk;
+   tk = x.tk;
+}
+
+
+Spl_cubic & Spl_cubic::operator=(const Spl_cubic & x)
+//!  @brief Overload = operator.
+{
+   bad_data = x.bad_data;
+   nb_path = x.nb_path;
+   Ak = x.Ak;
+   Bk = x.Bk;
+   Ck = x.Ck;
+   Dk = x.Dk;
+   tk = x.tk;
+   return *this;
+}
+
+
+short Spl_cubic::interpolating(const Real t, ColumnVector & s)
+//!  @brief Interpolating the spline at time t. Extrapolating is not allowed.
+{
+   if(bad_data)
+   {
+      cerr << "Spl_cubic::interpolating: data is not good. Problems occur in constructor." << endl;
+      return BAD_DATA;
+   }
+
+   for(int i = 1; i < tk.Ncols(); i++)
+      if( (t >= tk(i)) && (t < tk(i+1)) )
+      {
+         s = Ak.SubMatrix(1,nb_path,i,i)*pow(t - tk(i), 3) +
+             Bk.SubMatrix(1,nb_path,i,i)*pow(t - tk(i),2) +
+             Ck.SubMatrix(1,nb_path,i,i)*(t - tk(i)) +
+             Dk.SubMatrix(1,nb_path,i,i);
+         return 0;
+      }
+
+   cerr << "Spl_cubic::interpolating: t is out of range." << endl;
+   return NOT_IN_RANGE;
+}
+
+
+short Spl_cubic::first_derivative(const Real t, ColumnVector & ds)
+//!  @brief Spline first derivative at time t.
+{
+   if(bad_data)
+   {
+      cerr << "Spl_cubic::first_derivative: data is not good. Problems occur in constructor." << endl;
+      return BAD_DATA;
+   }
+
+   for(int i = 1; i < tk.Ncols(); i++)
+      if( (t >= tk(i)) && (t < tk(i+1)) )
+      {
+         ds = 3*Ak.SubMatrix(1,nb_path,i,i)*pow(t - tk(i), 2) +
+              2*Bk.SubMatrix(1,nb_path,i,i)*(t - tk(i)) +
+              Ck.SubMatrix(1,nb_path,i,i);
+         return 0;
+      }
+
+   cerr << "Spl_cubic::first_derivative: t not in range." << endl;
+   return NOT_IN_RANGE;
+}
+
+
+short Spl_cubic::second_derivative(const Real t, ColumnVector & ds)
+//!  @brief Spline second derivative at time t.
+{
+   if(bad_data)
+   {
+      cerr << "Spl_cubic::second_derivative: data is not good. Problems occur in constructor." << endl;
+      return BAD_DATA;
+   }
+
+   for(int i = 1; i < tk.Ncols(); i++)
+      if( (t >= tk(i)) && (t < tk(i+1)) )
+      {
+         ds = 6*Ak.SubMatrix(1,nb_path,i,i)*(t - tk(i)) +
+              2*Bk.SubMatrix(1,nb_path,i,i);
+         return 0;
+      }
+
+   cerr << "Spl_cubic::second_derivative: t not in range." << endl;
+   return NOT_IN_RANGE;
+}
+
+// ----------- E N D - E F F E C T O R   P A T H   W I T H   S P L I N E S  ----------
+
+Spl_path::Spl_path(const string & filename)
+/*!
+  @brief Constructor.
+  @param filename: Spline data.
+
+  Here is two examples of file. # is used as a comment, the rest of line is ignored.
+  The first line should contain the string CARTESIAN_SPACE or JOINT_SPACE. The following
+  number (3 in first example and 6 in the second) represents the number of points on 
+  each data line. 0, 0.5 and 1.0 in example 1 represents the time.
+
+Example 1:
+\verbatim
+#
+#
+#
+CARTESIAN_SPACE
+3
+0
+0.452100 -0.150050 -0.731800 
+0.5
+0.561821 -0.021244 -0.537842 
+1.0
+0.577857 0.268650 -0.323976 
+\endverbatim
+
+Example 2:
+\verbatim
+#
+#
+#
+JOINT_SPACE
+6
+0
+0 0 0 0 0 0
+1.
+0.2 -0.4 0.1 0.2 0.3 0.0
+2.0
+0.6 -0.8 0.2 0.4 0.4 0.0
+\endverbatim
+*/
+{
+   const char *ptr_filename = filename.c_str(); //transform string to *char
+
+   std::ifstream inpointfile(ptr_filename, std::ios::in);
+   point_map pts_map;
+
+   if(inpointfile)
+   {
+      double time;
+      int nb_path;
+      string temp;
+      pts_map.clear();
+
+#ifdef __WATCOMC__
+      char tempo[256];
+      inpointfile.getline(tempo,sizeof(tempo));
+      temp = tempo;
+#else
+      getline(inpointfile, temp);
+#endif
+      while(temp.substr(0,1) == "#") { // # comment
+#ifdef __WATCOMC__
+         inpointfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+#else
+         getline(inpointfile, temp);
+#endif
+      }
+
+      if(temp == "JOINT_SPACE")
+	  type = JOINT_SPACE;
+      else if (temp == "CARTESIAN_SPACE")
+	  type = CARTESIAN_SPACE;
+      else
+      {
+	  cerr << "Spl_path::Spl_path: wrong selection type. Should be joint space or cartesian space." << endl;
+	  return;
+      }
+	      
+#ifdef __WATCOMC__
+      inpointfile.getline(tempo,sizeof(tempo));
+      temp = tempo;
+      istrstream inputString1(tempo);
+#else
+      getline(inpointfile, temp);
+      istringstream inputString1(temp);
+#endif
+      inputString1 >> nb_path;
+      if(nb_path < 1)
+      {
+	  cerr << "Spl_path::Spl_path: number of splines should be >= 1." << endl;
+	  return;
+      }
+      ColumnVector p(nb_path);
+
+
+      while( !inpointfile.eof() )
+      {
+#ifdef __WATCOMC__
+         inpointfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+         istrstream inputString2(tempo);
+#else
+         getline(inpointfile, temp);
+         istringstream inputString2(temp);
+#endif
+
+         if(temp.substr(0,1) == " ")
+            break;
+         inputString2 >> time;
+	 final_time = time;
+
+#ifdef __WATCOMC__
+         inpointfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+         istrstream inputString3(tempo);
+#else
+         getline(inpointfile, temp);
+         istringstream inputString3(temp);
+#endif
+
+         for(int i = 1; i <= nb_path; i++)
+            inputString3 >> p(i);
+
+         pts_map.insert(point_map::value_type(time, p));
+      }
+   }
+   else
+      cerr << "Spl_path::Spl_path: can not open file " << filename.c_str() << endl;
+
+   // Spl_cubic class take as input a Matrix that contain the data.
+   int nb_pts, nb_path;
+   nb_pts = pts_map.size();
+   point_map::const_iterator iter = pts_map.begin();
+   nb_path = iter->second.Nrows();
+
+   Matrix pts(nb_path+1, nb_pts); pts = 0;
+   {
+      int i = 1;
+      for(iter = pts_map.begin(); iter != pts_map.end(); ++iter)
+      {
+         pts(1,i) = iter->first;
+         pts.SubMatrix(2, nb_path+1, i, i) = iter->second;
+         i++;
+      }
+   }
+   Spl_cubic::operator=(Spl_cubic(pts));
+}
+
+
+/*!
+  @fn Spl_path::Spl_path(const Matrix & pts)
+  @brief Constructor.
+*/
+Spl_path::Spl_path(const Matrix & pts): Spl_cubic(pts)
+{
+}
+
+
+/*!
+  @fn Spl_path::Spl_path(const Spl_path & x)
+  @brief Copy constructor.
+*/
+Spl_path::Spl_path(const Spl_path & x): Spl_cubic(x)
+{
+  type = x.type;
+  final_time = x.final_time;
+}
+
+
+Spl_path & Spl_path::operator=(const Spl_path & x)
+//!  @brief Overload = operator.
+{
+  type = x.type;
+  final_time = x.final_time;
+  Spl_cubic::operator=(x);
+  return *this;
+}
+
+short Spl_path::p(const Real t, ColumnVector & p)
+//!  @brief Position vector at time t.
+{
+   if(interpolating(t, p))
+   {
+      cerr << "Spl_path::p_pdot: problem with spline interpolating." << endl;
+      return -4;
+   }
+
+   return 0;
+}
+
+short Spl_path::p_pdot(const Real t, ColumnVector & p, ColumnVector & pdot)
+//!  @brief Position and velocity vector at time t.
+{
+   if(interpolating(t, p))
+   {
+      cerr << "Spl_path::p_pdot: problem with spline interpolating." << endl;
+      return -4;
+   }
+   if(first_derivative(t, pdot))
+   {
+      cerr << "Spl_path::p_pdot: problem with spline first_derivative." << endl;
+      return -4;
+   }
+
+   return 0;
+}
+
+short Spl_path::p_pdot_pddot(const Real t, ColumnVector & p, ColumnVector & pdot,
+                             ColumnVector & pdotdot)
+//! @brief Position, velocity and acceleration vector at time t.
+{
+   if(interpolating(t, p))
+   {
+      cerr << "Spl_path::p_pdot_pdotdot: problem with spline interpolating." << endl;
+      return -4;
+   }
+   if(first_derivative(t, pdot))
+   {
+      cerr << "Spl_path::p_pdot_pdotdot: problem with spline first_derivative." << endl;
+      return -4;
+   }
+   if(second_derivative(t, pdotdot))
+   {
+      cerr << "Spl_path::p_pdot_pdotdot: problem with spline first_derivative." << endl;
+      return -4;
+   }
+   return 0;
+}
+
+// -------------------- Q U A T E R N I O N  S P L I N E S -------------------
+
+
+Spl_Quaternion::Spl_Quaternion(const string & filename)
+/*!
+  @brief Constructor.
+  @param filename: Quaternions spline data.
+
+Here is an exemple of file. # is used as comment, the rest of the line is
+ignored. 0, 0.5 and 1.0 are the time at the control points. R indicated that the 
+quaternion at the control point is obtained from a rotation matrix, and the data 
+(9 elements of the matrix) is on the next line. Instead of R one could use Q to 
+indicate a quaternion and the following line will contain 4 elements.
+
+\verbatim
+#
+#
+#
+0
+R
+1.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 -0.000000 -1.000000
+0.5
+R
+0.999943 0.008696 -0.006149 0.009042 -0.998237 0.058659 -0.005628 -0.058711 -0.998259
+1.0
+R
+0.961882 0.254807 0.099282 0.223474 -0.941661 0.251662 0.157616 -0.219882 -0.962709
+\endverbatim
+*/
+{
+   const char *ptr_filename = filename.c_str(); //transform string to *char
+
+   std::ifstream inquatfile(ptr_filename, std::ios::in);
+
+   if(inquatfile)
+   {
+      double time;
+      string temp;
+      Matrix R(3,3);
+      Quaternion q;
+      quat_data.clear();
+#ifdef __WATCOMC__
+      char tempo[256];
+#endif
+
+      while( !inquatfile.eof() )
+      {
+#ifdef __WATCOMC__
+         inquatfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+#else
+         getline(inquatfile, temp);
+#endif
+         while(temp.substr(0,1) == "#") {
+#ifdef __WATCOMC__
+            inquatfile.getline(tempo,sizeof(tempo));
+            temp = tempo;
+#else
+            getline(inquatfile, temp);
+#endif
+         }
+#ifdef __WATCOMC__
+         istrstream inputString(tempo);
+#else
+         istringstream inputString(temp);
+#endif
+         if(temp.substr(0,1) == " ")
+            break;
+         inputString >> time;
+
+#ifdef __WATCOMC__
+         inquatfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+#else
+         getline(inquatfile, temp);
+#endif
+         if( (temp.substr(0,1) == "r") || (temp.substr(0,1) == "R") )
+         {
+#ifdef __WATCOMC__
+            inquatfile.getline(tempo,sizeof(tempo));
+            temp = tempo;
+            istrstream inputString(tempo);
+#else
+            getline(inquatfile, temp);
+            istringstream inputString(temp);
+#endif
+            inputString >> R(1,1) >> R(1,2) >> R(1,3) >> R(2,1) >> R(2,2) >>
+            R(2,3) >> R(3,1) >> R(3,2) >> R(3,3);
+            q = Quaternion(R);
+         }
+         else if( (temp.substr(0,1) == "q") || (temp.substr(0,1) == "Q") )
+         {
+#ifdef __WATCOMC__
+            inquatfile.getline(tempo,sizeof(tempo));
+            temp = tempo;
+            istrstream inputString(tempo);
+#else
+            getline(inquatfile, temp);
+            istringstream inputString(temp);
+#endif
+            inputString >> R(1,1) >> R(1,2) >> R(1,3) >> R(2,1);
+            q = Quaternion(R(1,1), R(1,2), R(1,3), R(2,1));
+         }
+         else if(temp.substr(0,1) == "")
+         {
+         }
+         else
+         {
+            cerr << "Spl_Quaternion::Spl_Quaternion: format of input file "
+            << filename.c_str() << " is incorrect" << endl;
+         }
+
+         quat_data.insert( quat_map::value_type(time, q));
+      }
+   }
+   else
+   {
+      cerr << "Spl_Quaternion::Spl_Quaternion: can not open file "
+      << filename.c_str() << endl;
+   }
+}
+
+
+Spl_Quaternion::Spl_Quaternion(const quat_map & quat)
+//!  @brief Constructor.
+{
+   quat_data = quat;
+}
+
+
+Spl_Quaternion::Spl_Quaternion(const Spl_Quaternion & x)
+//!  @brief Copy constructor.
+{
+   quat_data = x.quat_data;
+}
+
+
+Spl_Quaternion & Spl_Quaternion::operator=(const Spl_Quaternion & x)
+//!  @brief Overload = operator.
+{
+   quat_data = x.quat_data;
+   return *this;
+}
+
+
+
+short Spl_Quaternion::quat(const Real t, Quaternion & s)
+/*!
+  @brief Quaternion interpollation.
+
+  \f[
+    S_n(t) = Squad(q_n,a_n, a(n+1),q(n+1),t)
+  \f]
+*/
+{
+   Real dt=0;
+   Quaternion ds;
+   quat_map::const_iterator iter1 = quat_data.begin(), iter2;
+
+   if( t == iter1->first)
+   {
+      s = iter1->second;
+      return 0;
+   }
+
+   // Point to interpolate is between the first and the second point. Use Slerp function
+   // since there is not enough points for Squad. Use dt since Slerp and Squad functions
+   // need t from 0 to 1.
+   iter2 = iter1;
+   iter2++;
+   if( t < iter2->first)
+   {
+      dt = (t - iter1->first)/(iter2->first - iter1->first);
+      s  = Slerp(iter1->second, iter2->second, dt);
+      return 0;
+   }
+
+
+   // From second element to element N-2.
+   //    for(iter1 = ++quat_data.begin(); iter1 != ----quat_data.end(); ++iter1)
+   //    for(iter1 = ++iter1; iter1 != ----quat_data.end(); ++iter1)
+   for(iter1 = iter2; iter1 != ----quat_data.end(); ++iter1)
+   {
+      iter2=iter1;
+      iter2++;
+      if( (t >= iter1->first) && (t < iter2->first) )
+      {
+         dt = (t - iter1->first)/(iter2->first - iter1->first);
+
+         Quaternion qn_  = (--iter1)->second,  // q(n-1)
+                           qn   = (++iter1)->second,  // q(n)
+                                  qn_1 = (++iter1)->second,  // q(n+1)
+                                         qn_2 = (++iter1)->second,  // q(n+2)
+                                                q_tmp;
+         ----iter1;
+
+         // Intermediate point a(n) and a(n+1)
+         Quaternion an   = qn*(((qn.i()*qn_1).Log() + (qn.i()*qn_).Log())/-4).exp(),
+                           an_1 = qn_1*(((qn_1.i()*qn_2).Log() + (qn_1.i()*qn).Log())/-4).exp();
+
+         s  = Squad(qn, an, an_1, qn_1, dt);
+         return 0;
+      }
+   }
+
+   // Interpolation between last two points.
+   iter2 = iter1; iter2++;
+   if( (t >= iter1->first) && (t <= iter2->first) )
+   {
+      dt = (t - iter1->first)/(iter2->first - iter1->first);
+      s = Slerp(iter1->second, iter2->second, dt);
+      return 0;
+   }
+
+   cerr << "Spl_Quaternion::quat_w: t not in range." << endl;
+   return NOT_IN_RANGE;
+}
+
+short Spl_Quaternion::quat_w(const Real t, Quaternion & s, ColumnVector & w)
+//!  @brief Quaternion interpollation and angular velocity.
+{
+   Real dt=0;
+   Quaternion ds;
+   quat_map::const_iterator iter1 = quat_data.begin(), iter2;
+
+   if( t == iter1->first)
+   {
+      s = iter1->second;
+      w = ColumnVector(3); w = 0.0;
+      return 0;
+   }
+
+   // Point to interpolate is between the first and the second point. Use Slerp function
+   // since there is not enough points for Squad. Use dt since Slerp and Squad functions
+   // need t from 0 to 1.
+   iter2 = iter1;
+   iter2++;
+   if( t < iter2->first)
+   {
+      dt = (t - iter1->first)/(iter2->first - iter1->first);
+      s  = Slerp(iter1->second, iter2->second, dt);
+      ds = Slerp_prime(iter1->second, iter2->second, dt);
+      w = Omega(s, ds);
+
+      return 0;
+   }
+
+   // From second element to element N-2.
+   //    for(iter1 = ++quat_data.begin(); iter1 != ----quat_data.end(); ++iter1)
+   //    for(iter1 = ++iter1; iter1 != ----quat_data.end(); ++iter1)
+   for(iter1 = iter2; iter1 != ----quat_data.end(); ++iter1)
+   {
+      iter2=iter1;
+      iter2++;
+      if( (t >= iter1->first) && (t < iter2->first) )
+      {
+         dt = (t - iter1->first)/(iter2->first - iter1->first);
+
+         Quaternion qn_  = (--iter1)->second,  // q(n-1)
+                           qn   = (++iter1)->second,  // q(n)
+                                  qn_1 = (++iter1)->second,  // q(n+1)
+                                         qn_2 = (++iter1)->second,  // q(n+2)
+                                                q_tmp;
+         ----iter1;
+
+         // Intermediate point a(n) and a(n+1)
+         Quaternion an   = qn*(((qn.i()*qn_1).Log() + (qn.i()*qn_).Log())/-4).exp(),
+                           an_1 = qn_1*(((qn_1.i()*qn_2).Log() + (qn_1.i()*qn).Log())/-4).exp();
+
+         s  = Squad(qn, an, an_1, qn_1, dt);
+         ds = Squad_prime(qn, an, an_1, qn_1, dt);
+         w = Omega(s, ds);
+         return 0;
+      }
+   }
+
+   // Interpolation between last two points.
+   iter2 = iter1; iter2++;
+   if( (t >= iter1->first) && (t <= iter2->first) )
+   {
+      dt = (t - iter1->first)/(iter2->first - iter1->first);
+      s = Slerp(iter1->second, iter2->second, dt);
+      ds = Slerp_prime(iter1->second, iter2->second, dt);
+      w = Omega(s, ds);
+      return 0;
+   }
+
+   cerr << "Spl_Quaternion::quat_w: t not in range." << endl;
+   return NOT_IN_RANGE;
+}
+
+
+// -----------------------------------------------------------------------------------------------
+
+
+Trajectory_Select::Trajectory_Select()
+//!  @brief Constructor.
+{
+    type = NONE;
+    quaternion_active = false;
+}
+
+
+Trajectory_Select::Trajectory_Select(const string & filename)
+/*!
+  @brief Constructor.
+  @param filename: File containing spline data. 
+
+  The file can be a quaternion file (Spl_Quaternion) or path 
+  file (Spl_path).
+*/
+{
+    set_trajectory(filename);
+}
+
+
+Trajectory_Select & Trajectory_Select::operator=(const Trajectory_Select & x)
+//!  @brief Overload = operator.
+{
+    type = x.type;
+    if(x.quaternion_active)
+    {
+	quaternion_active = x.quaternion_active;
+	path_quat = x.path_quat;
+    }
+    else
+	path = x.path;
+
+    return *this;
+}
+
+
+void Trajectory_Select::set_trajectory(const string & filename)
+//!  @brief Trajectory selection.
+{
+   const char *ptr_filename = filename.c_str(); //transform string to *char
+
+   std::ifstream inpointfile(ptr_filename, std::ios::in);
+
+   if(inpointfile)
+   {
+      string temp;
+
+#ifdef __WATCOMC__
+      char tempo[256];
+      inpointfile.getline(tempo,sizeof(tempo));
+      temp = tempo;
+#else
+      getline(inpointfile, temp);
+#endif
+      while(temp.substr(0,1) == "#") { // # comment
+#ifdef __WATCOMC__
+         inpointfile.getline(tempo,sizeof(tempo));
+         temp = tempo;
+#else
+         getline(inpointfile, temp);
+#endif
+      }
+
+      if( (temp == "JOINT_SPACE") || (temp == "CARTESIAN_SPACE") )
+      {  
+	  path = Spl_path(filename);
+	  type = path.get_type();
+	  quaternion_active = false;
+      }
+      else
+      {
+	  path_quat = Spl_Quaternion(filename);
+	  type = CARTESIAN_SPACE;
+	  quaternion_active = true;
+      }
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+
+
+
+
Index: Motion/roboop/trajectory.h
===================================================================
RCS file: Motion/roboop/trajectory.h
diff -N Motion/roboop/trajectory.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/trajectory.h	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,190 @@
+/*
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+Reference:
+
+[1] J. Angeles, Fundamentals of Robotic Mechanical Systems: Theory, Methods and Algorithms,
+    Springer-Verlag, Mechanical Engineering Series, 1997, ISBN: 0-387-94540-7.
+
+[2] E.B. Dam, M. Koch and M. Lillholm, "Quaternions, Interpolation and Animation",
+    tech report of University of Copenhagen, number: DIKU-TR-98/5, 1998.
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/05/22: Etienne Lachance
+   -Added class Trajectory_Select.
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+
+#ifndef TRAJECTORY_H
+#define TRAJECTORY_H
+
+/*!
+  @file trajectory.h
+  @brief Header file for trajectory generation class.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_trajectory_rcsid[] = "$Id: trajectory.h,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+
+#ifdef _MSC_VER                         // Microsoft
+//#include <string.h>
+//#include <iostream.h>
+#pragma warning (disable:4786)  /* Disable decorated name truncation warnings */
+#endif
+//#include <string>
+//#include <iostream>
+
+//#include <fstream>
+#ifdef __WATCOMC__
+#include <strstrea.h>
+#else
+#include <sstream>
+#endif
+#include <map>
+#include "quaternion.h"
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#define K_ZER0          1
+#define BAD_DATA       -1
+#define EXTRAPOLLATION -2
+#define NOT_IN_RANGE   -3
+
+/*!
+  @class Spl_cubic
+  @brief Natural cubic splines class.
+*/
+class Spl_cubic
+{
+public:
+   Spl_cubic(){};
+   Spl_cubic(const Matrix & pts);
+   Spl_cubic(const Spl_cubic & x);
+   Spl_cubic & operator=(const Spl_cubic & x);
+   short interpolating(const Real t, ColumnVector & s);
+   short first_derivative(const Real t, ColumnVector & ds);
+   short second_derivative(const Real t, ColumnVector & dds);
+private:
+   int nb_path;    //!< Number of path, i.e: path in x,y,z nb_path=3
+   Matrix
+   Ak, Bk, Ck, Dk;
+   RowVector tk;   //!< Time at control points.
+   bool bad_data;  //!< Status flag.
+};
+
+
+#define NONE            0
+#define JOINT_SPACE     1
+#define CARTESIAN_SPACE 2
+
+//! @brief Data at control points.
+typedef map< Real, ColumnVector, less< Real > > point_map;
+
+
+/*!
+  @class Spl_path
+  @brief Cartesian or joint space trajectory
+*/
+class Spl_path : public Spl_cubic
+{
+public:
+   Spl_path():Spl_cubic(){};
+   Spl_path(const string & filename);
+   Spl_path(const Matrix & x);
+   Spl_path(const Spl_path & x);
+   Spl_path & operator=(const Spl_path & x);
+   short p(const Real time, ColumnVector & p);
+   short p_pdot(const Real time, ColumnVector & p, ColumnVector & pdot);
+   short p_pdot_pddot(const Real time, ColumnVector & p, ColumnVector & pdot,
+                      ColumnVector & pdotdot);
+   short get_type(){ return type; }
+   double get_final_time(){ return final_time; }
+   
+private:
+   short type;        //!< Cartesian space or joint space.
+   double final_time; //!< Spline final time.
+};
+
+
+//! @brief Data at control points.
+typedef map< Real, Quaternion, less< Real > > quat_map;
+
+
+/*!
+  @class Spl_Quaternion
+  @brief Cubic quaternions spline.
+*/
+class Spl_Quaternion
+{
+public:
+   Spl_Quaternion(){}
+   Spl_Quaternion(const string & filename);
+   Spl_Quaternion(const quat_map & quat);
+   Spl_Quaternion(const Spl_Quaternion & x);
+   Spl_Quaternion & operator=(const Spl_Quaternion & x);
+   short quat(const Real t, Quaternion & s);
+   short quat_w(const Real t, Quaternion & s, ColumnVector & w);
+private:
+   quat_map quat_data;  //!< Data at control points.
+};
+
+
+/*!
+  @class Trajectory_Select
+  @brief Trajectory class selection.
+*/
+class Trajectory_Select
+{
+public:
+    Trajectory_Select();
+    Trajectory_Select(const string & filename);
+    Trajectory_Select(const Trajectory_Select & x);
+    Trajectory_Select & operator=(const Trajectory_Select & x);
+
+    void set_trajectory(const string & filename);
+
+    short type;               //!< Cartesian or joint space
+    Spl_path path;            //!< Spl_path instance.
+    Spl_Quaternion path_quat; //!< Spl_Quaternion instance.
+private:
+    bool quaternion_active;   //!< Using Spl_Quaternion.
+};
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
Index: Motion/roboop/utils.cpp
===================================================================
RCS file: Motion/roboop/utils.cpp
diff -N Motion/roboop/utils.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/utils.cpp	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,351 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Added functions x_prod_matrix, vec_dot_prod, Integ_Trap and sign.
+   -Working on Runge_Kutta4_etienne.
+
+2004/07/01: Etienne Lachance
+   -Removed function vec_x_prod and vec_dot_prod. Now we use CrossProduct
+    and DotProduct, from Newmat library.
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+/*!
+  @file utils.cpp
+  @brief Utility functions.
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: utils.cpp,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#include "robot.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+
+ReturnMatrix x_prod_matrix(const ColumnVector & x)
+//!  @brief Cross product matrix
+{
+   Matrix S(3,3); S = 0.0;
+   S(1,2) = -x(3); S(1,3) =  x(2);
+   S(2,1) =  x(3);                 S(2,3) = -x(1);
+   S(3,1) = -x(2); S(3,2) =  x(1);
+
+   S.Release(); return (S);
+}
+
+
+ReturnMatrix Integ_Trap(const ColumnVector & present, ColumnVector & past,
+                        const Real dt)
+  //!  @brief Trapezoidal integration.
+{
+   ColumnVector integration(present.Nrows());
+   integration = (past+present)*0.5*dt;
+   past = present;
+
+   integration.Release();
+   return ( integration );
+}
+
+
+void Runge_Kutta4_Real_time(ReturnMatrix (*xdot)(Real time, const Matrix & xin,
+						 bool & exit, bool & init),
+			    const Matrix & xo, Real to, Real tf, int nsteps)
+//!  @brief Fixed step size fourth-order Runge-Kutta integrator.
+{
+    static Real h, h2, t;
+    static Matrix k1, k2, k3, k4, x;
+    static bool first_pass = true, init = false, exit = false;
+
+    if(first_pass || init)
+    {
+	h = (tf-to)/nsteps;
+	h2 = h/2.0;
+	t = to;
+	x = xo;
+	first_pass = false;
+    }
+      k1 = (*xdot)(t, x, exit, init) * h;
+      if(exit) return;
+      k2 = (*xdot)(t+h2, x+k1*0.5, exit, init)*h;
+      if(exit) return;
+      k3 = (*xdot)(t+h2, x+k2*0.5, exit, init)*h;
+      if(exit) return;
+      k4 = (*xdot)(t+h, x+k3, exit, init)*h;
+      if(exit) return;
+      x = x + (k1*0.5+ k2 + k3 + k4*0.5)*(1.0/3.0);
+      t += h;
+}
+
+void Runge_Kutta4_Real_time(ReturnMatrix (*xdot)(const Real time, const Matrix & xin),
+			    const Matrix & xo, const Real to, const Real tf, const int nsteps)
+{
+    static Real h, h2, t;
+    static Matrix k1, k2, k3, k4, x;
+    static bool first_pass = true;
+
+    if(first_pass)
+    {
+	h = (tf-to)/nsteps;
+	h2 = h/2.0;
+	t = to;
+	x = xo;
+	first_pass = false;
+    }
+      k1 = (*xdot)(t, x) * h;
+      t += h2;
+      k2 = (*xdot)(t, x+k1*0.5)*h;
+      k3 = (*xdot)(t, x+k2*0.5)*h;
+      t += h2;
+      k4 = (*xdot)(t, x+k3)*h;
+      x = x + (k1*0.5+ k2 + k3 + k4*0.5)*(1.0/3.0);
+}
+
+
+void Runge_Kutta4(ReturnMatrix (*xdot)(Real time, const Matrix & xin),
+            const Matrix & xo, Real to, Real tf, int nsteps,
+            RowVector & tout, Matrix & xout)
+//!  @brief Fixed step size fourth-order Runge-Kutta integrator.
+{
+   Real h, h2, t;
+   Matrix k1, k2, k3, k4, x;
+
+   h = (tf-to)/nsteps;
+   h2 = h/2.0;
+   t = to;
+   x = xo;
+   xout = Matrix(xo.Nrows(),(nsteps+1)*xo.Ncols());
+   xout.SubMatrix(1,xo.Nrows(),1,xo.Ncols()) = x;
+   tout = RowVector(nsteps+1);
+   tout(1) = to;
+   for (int i = 1; i <= nsteps; i++) {
+      k1 = (*xdot)(t, x) * h;
+      k2 = (*xdot)(t+h2, x+k1*0.5)*h;
+      k3 = (*xdot)(t+h2, x+k2*0.5)*h;
+      k4 = (*xdot)(t+h, x+k3)*h;
+      x = x + (k1*0.5+ k2 + k3 + k4*0.5)*(1.0/3.0);
+      t += h;
+      tout(i+1) = t;
+      xout.SubMatrix(1,xo.Nrows(),i*xo.Ncols()+1,(i+1)*xo.Ncols()) = x;
+   }
+}
+
+ReturnMatrix rk4(const Matrix & x, const Matrix & dxdt, Real t, Real h,
+                 ReturnMatrix (*xdot)(Real time, const Matrix & xin))
+/*!
+  @brief Compute one Runge-Kutta fourth order step
+
+  adapted from:
+  Numerical Recipes in C, The Art of Scientific Computing,
+  Press, William H. and Flannery, Brian P. and Teukolsky, Saul A.
+  and Vetterling, William T., Cambridge University Press, 1988.
+*/
+{
+   Matrix xt, xout, dxm, dxt;
+   Real th, hh, h6;
+
+   hh = h*0.5;
+   h6 = h/6.0;
+   th = t + hh;
+   xt = x + hh*dxdt;
+   dxt = (*xdot)(th,xt);
+   xt = x + hh*dxt;
+   dxm = (*xdot)(th,xt);
+   xt = x + h*dxm;
+   dxm += dxt;
+   dxt = (*xdot)(t+h,xt);
+   xout = x+h6*(dxdt+dxt+2.0*dxm);
+
+   xout.Release(); return xout;
+}
+
+#define PGROW -0.20
+#define PSHRNK -0.25
+#define FCOR 0.06666666
+#define SAFETY 0.9
+#define ERRCON 6.0E-4
+
+void rkqc(Matrix & x, Matrix & dxdt, Real & t, Real htry,
+          Real eps, Matrix & xscal, Real & hdid, Real & hnext,
+          ReturnMatrix (*xdot)(Real time, const Matrix & xin))
+/*!
+  @brief Compute one adaptive step based on two rk4.
+
+  adapted from:
+  Numerical Recipes in C, The Art of Scientific Computing,
+  Press, William H. and Flannery, Brian P. and Teukolsky, Saul A.
+  and Vetterling, William T., Cambridge University Press, 1988.
+*/
+{
+   Real tsav, hh, h, temp, errmax;
+   Matrix dxsav, xsav, xtemp;
+
+   tsav = t;
+   xsav = x;
+   dxsav = dxdt;
+   h = htry;
+   for(;;) {
+      hh = 0.5*h;
+      xtemp = rk4(xsav,dxsav,tsav,hh,xdot);
+      t = tsav+hh;
+      dxdt = (*xdot)(t,xtemp);
+      x = rk4(xtemp,dxdt,t,hh,xdot);
+      t = tsav+h;
+      if(t == tsav) {
+         cerr << "Step size too small in routine RKQC\n";
+         exit(1);
+      }
+      xtemp = rk4(xsav,dxsav,tsav,h,xdot);
+      errmax = 0.0;
+      xtemp = x-xtemp;
+      for(int i = 1; i <= x.Nrows(); i++) {
+         temp = fabs(xtemp(i,1)/xscal(i,1));
+         if(errmax < temp) errmax = temp;
+      }
+      errmax /= eps;
+      if(errmax <= 1.0) {
+         hdid = h;
+         hnext = (errmax > ERRCON ?
+                  SAFETY*h*exp(PGROW*log(errmax)) : 4.0*h);
+         break;
+      }
+      h = SAFETY*h*exp(PSHRNK*log(errmax));
+   }
+   x += xtemp*FCOR;
+}
+
+#define MAXSTP 10000
+#define TINY 1.0e-30
+
+void odeint(ReturnMatrix (*xdot)(Real time, const Matrix & xin),
+            Matrix & xo, Real to, Real tf, Real eps, Real h1, Real hmin,
+            int & nok, int & nbad,
+            RowVector & tout, Matrix & xout, Real dtsav)
+/*!
+  @brief Integrate the ordinary differential equation xdot from time to
+   to time tf using an adaptive step size strategy 
+
+   adapted from:
+   Numerical Recipes in C, The Art of Scientific Computing,
+   Press, William H. and Flannery, Brian P. and Teukolsky, Saul A.
+   and Vetterling, William T., Cambridge University Press, 1988.
+*/
+{
+   Real tsav, t, hnext, hdid, h;
+   RowVector tv(1);
+
+   Matrix xscal, x, dxdt;
+
+   tv = to;
+   tout = tv;
+   xout = xo;
+   xscal = xo;
+   t = to;
+   h = (tf > to) ? fabs(h1) : -fabs(h1);
+   nok = (nbad) = 0;
+   x = xo;
+   tsav = t;
+   for(int nstp = 1; nstp <= MAXSTP; nstp++){
+      dxdt = (*xdot)(t,x);
+      for(int i = 1; i <= x.Nrows(); i++)
+         xscal(i,1) = fabs(x(i,1))+fabs(dxdt(i,1)*h)+TINY;
+      if((t+h-tf)*(t+h-to) > 0.0) h = tf-t;
+      rkqc(x,dxdt,t,h,eps,xscal,hdid,hnext,xdot);
+      if(hdid == h) ++(nok); else ++(nbad);
+      if((t-tf)*(tf-to) >= 0.0) {
+         xo = x;
+         tv = t;
+         tout = tout | tv;
+         xout = xout | x;
+         return;
+      }
+      if(fabs(t-tsav) > fabs(dtsav)) {
+         tv = t;
+         tout = tout | tv;
+         xout = xout | x;
+         tsav = t;
+      }
+      if(fabs(hnext) <= hmin) {
+         cerr << "Step size too small in ODEINT\n";
+         cerr << setw(7) << setprecision(3) << (tout & xout).t();
+         exit(1);
+      }
+      h = hnext;
+   }
+   cerr << "Too many step in routine ODEINT\n";
+   exit(1);
+}
+
+ReturnMatrix sign(const Matrix & x)
+//!  @brief Sign of a matrix.
+{
+   Matrix out = x;
+
+   for(int i = 1; i <= out.Ncols(); i++) {
+      for(int j = 1; j <= out.Nrows(); j++) {
+         if(out(j,i) > 0.0) {
+            out(j,i) = 1.0;
+         } else if(out(j,i) < 0.0) {
+            out(j,i) = -1.0;
+         }
+      }
+   }
+
+   out.Release(); return out;
+}
+
+
+short sign(const Real x)
+  //!  @brief Sign of real.
+{
+   short i = 1;
+   if(x > 0.0)
+      i = 1;
+   else
+      i = -1;
+
+   return (i);
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Motion/roboop/utils.h
===================================================================
RCS file: Motion/roboop/utils.h
diff -N Motion/roboop/utils.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/utils.h	14 Jul 2004 02:32:12 -0000	1.4
@@ -0,0 +1,158 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+   -Added doxygen documentation.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+#ifndef __cplusplus
+#error Must use C++ for the type Robot
+#endif
+#ifndef UTILS_H
+#define UTILS_H
+
+/*!
+  @file utils.h
+  @brief Utility header file.
+*/
+
+//! @brief RCS/CVS version.
+static const char header_utils_rcsid[] = "$Id: utils.h,v 1.4 2004/07/14 02:32:12 ejt Exp $";
+
+#ifdef _MSC_VER                         // Microsoft
+#pragma warning (disable:4786)  /* Disable decorated name truncation warnings */
+#endif
+#include <stdio.h>
+#include <vector>
+#include <stdexcept>
+#define WANT_STRING                  /* include.h will get string fns */
+#define WANT_STREAM                  /* include.h will get stream fns */
+#define WANT_FSTREAM                 /* include.h will get fstream fns */
+#define WANT_MATH                    /* include.h will get math fns */
+                                     /* newmatap.h will get include.h */
+
+#include "newmatap.h"                /* need matrix applications */
+
+#include "newmatio.h"                /* need matrix output routines */
+#include "config.h"
+
+#ifdef use_namespace
+namespace ROBOOP {
+  using namespace NEWMAT;
+#endif
+
+#ifndef __WATCOMC__
+using namespace std;
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979
+#endif
+
+// global variables
+
+extern Real fourbyfourident[];
+extern Real threebythreeident[];
+
+// vector operation 
+
+ReturnMatrix x_prod_matrix(const ColumnVector & x);
+
+// numerical analysis tools
+
+ReturnMatrix Integ_Trap(const ColumnVector & present, ColumnVector & past, const Real dt);
+
+void Runge_Kutta4(ReturnMatrix (*xdot)(Real time, const Matrix & xin),
+                  const Matrix & xo, Real to, Real tf, int nsteps,
+                  RowVector & tout, Matrix & xout);
+
+void Runge_Kutta4_Real_time(ReturnMatrix (*xdot)(Real time, const Matrix & xin),
+                            const Matrix & xo, Real to, Real tf, int nsteps);
+
+void Runge_Kutta4_Real_time(ReturnMatrix (*xdot)(Real time, const Matrix & xin,
+                            bool & exit, bool & init),
+                            const Matrix & xo, Real to, Real tf, int nsteps);
+
+void odeint(ReturnMatrix (*xdot)(Real time, const Matrix & xin),
+            Matrix & xo, Real to, Real tf, Real eps, Real h1, Real hmin,
+            int & nok, int & nbad,
+            RowVector & tout, Matrix & xout, Real dtsav);
+
+ReturnMatrix sign(const Matrix & x);
+
+short sign(const Real x);
+
+// translation 
+ReturnMatrix trans(const ColumnVector & a);
+
+// rotation matrices 
+ReturnMatrix rotx(const Real alpha);
+ReturnMatrix roty(const Real beta);
+ReturnMatrix rotz(const Real gamma);
+ReturnMatrix rotk(const Real theta, const ColumnVector & k);
+
+ReturnMatrix rpy(const ColumnVector & a);
+ReturnMatrix eulzxz(const ColumnVector & a);
+ReturnMatrix rotd(const Real theta, const ColumnVector & k1, const ColumnVector & k2);
+
+
+// inverse on rotation matrices 
+ReturnMatrix irotk(const Matrix & R);
+ReturnMatrix irpy(const Matrix & R);
+ReturnMatrix ieulzxz(const Matrix & R);
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/extra/bench.cpp
===================================================================
RCS file: Motion/roboop/extra/bench.cpp
diff -N Motion/roboop/extra/bench.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/bench.cpp	14 Jul 2004 02:29:41 -0000	1.4
@@ -0,0 +1,144 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston,  MA 02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+
+2004/07/02: Etienne Lachance
+    -Added doxygen documentation.
+-------------------------------------------------------------------------------
+*/
+
+/*! 
+  @file bench.cpp
+  @brief A benchmark file.
+
+  Prints the time, on the console, to perform certain operations.
+*/
+
+static const char rcsid[] = "$Id: bench.cpp,v 1.4 2004/07/14 02:29:41 ejt Exp $";
+
+#include <time.h>
+
+#ifdef _WIN32          /* Windows 95/NT */
+#ifdef __GNUG__        /* Cygnus Gnu C++ for win32*/
+#include <windows.h>
+#define clock() GetTickCount() /* quick fix for bug in clock() */
+#endif
+#endif
+
+#include "robot.h"
+
+#ifdef use_namespace
+using namespace ROBOOP;
+#endif
+
+#define NTRY 2000
+
+Real PUMA560_data[] =
+   {0.0, 0.0, 0.0, 0.0, M_PI/2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.35, 0.0, 0.0,
+    0.0, 0.0, 0.0, 0.4318, 0.0, 17.4, -0.3638, 0.006, 0.2275, 0.13, 0.0, 0.0, 0.524, 0.0, 0.539,
+    0.0, 0.0, 0.15005, 0.0203, -M_PI/2.0, 4.8, -0.0203, -0.0141, 0.07, 0.066, 0.0, 0.0, 0.086, 0.0, 0.0125,
+    0.0, 0.0, 0.4318, 0.0, M_PI/2.0, 0.82, 0.0, 0.019, 0.0, 0.0018, 0.0, 0.0, 0.0013, 0.0, 0.0018,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 0.34, 0.0, 0.0, 0.0, 0.0003, 0.0, 0.0, 0.0004, 0.0, 0.0003,
+    0.0, 0.0, 0.0, 0.0, 0.0, 0.09, 0.0, 0.0, 0.032, 0.00015, 0.0, 0.0, 0.00015, 0.0, 0.00004};
+
+int main(void)
+{
+   int i;
+   clock_t start, end;
+   Matrix initrob(6,15), thomo, temp2;
+   ColumnVector q(6), qs(6), temp;
+   Robot robot;
+
+   initrob << PUMA560_data;
+   robot = Robot(initrob);
+   q = M_PI/6.0;
+
+   q = M_PI/4.0;
+   printf("Begin compute Forward Kinematics\n");
+   start = clock();
+   for (i = 1; i <= NTRY; i++) {
+      robot.set_q(q);
+      temp2 = robot.kine();
+   }
+   end = clock();
+   printf("MilliSeconds %6.2f\n", ((end - start) / (Real)CLOCKS_PER_SEC)*1000.0/NTRY);
+   printf("end \n");
+
+   qs = 1.0;
+   qs(1) = M_PI/16.0;
+   robot.set_q(q);
+   thomo = robot.kine();
+   printf("Begin compute Inverse Kinematics\n");
+   start = clock();
+   for (i = 1; i <= NTRY; i++) {
+      robot.set_q(qs);
+      temp = robot.inv_kin(thomo);
+   }
+   end = clock();
+   printf("MilliSeconds %6.2f\n", ((end - start) / (Real)CLOCKS_PER_SEC)*1000.0/NTRY);
+   printf("end \n");
+
+   printf("Begin compute Jacobian\n");
+   start = clock();
+   for (i = 1; i <= NTRY; i++) {
+      robot.set_q(q);
+      temp2 = robot.jacobian();
+   }
+   end = clock();
+   printf("MilliSeconds %6.2f\n", ((end - start) / (Real)CLOCKS_PER_SEC)*1000.0/NTRY);
+   printf("end \n");
+
+   printf("Begin compute Torque\n");
+   start = clock();
+   for (i = 1; i <= NTRY; i++) {
+      temp = robot.torque(q,q,q);
+   }
+   end = clock();
+   printf("MilliSeconds %6.2f\n", ((end - start) / (Real)CLOCKS_PER_SEC)*1000.0/NTRY);
+   printf("end \n");
+
+   printf("Begin acceleration\n");
+   start = clock();
+   for (i = 1; i <= NTRY; i++) {
+      temp = robot.acceleration(q,q,q);
+   }
+   end = clock();
+   printf("MilliSeconds %6.2f\n", ((end - start) / (Real)CLOCKS_PER_SEC)*1000.0/NTRY);
+   printf("end \n");
+
+   return 0;
+}
+
+
+
Index: Motion/roboop/extra/demo.cpp
===================================================================
RCS file: Motion/roboop/extra/demo.cpp
diff -N Motion/roboop/extra/demo.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/demo.cpp	14 Jul 2004 02:29:41 -0000	1.4
@@ -0,0 +1,625 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2003/02/03: Etienne Lachance
+   -Added quaternions example in homogen_demo.
+   -Using function set_plot2d for gnuplot graphs. 
+   -Declare vector with "dof" instead of hardcoded value.
+   -Changed RobotMotor to Robot.
+
+2003/29/04: Etienne Lachance
+   -Using Robot("conf/puma560_dh.conf", "PUMA560_DH") in kinematics functions.
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+
+*/
+
+static const char rcsid[] = "$Id: demo.cpp,v 1.4 2004/07/14 02:29:41 ejt Exp $";
+
+#include "robot.h"
+#include "quaternion.h"
+#include "gnugraph.h"
+
+#ifdef use_namespace
+using namespace ROBOOP;
+#endif
+
+void homogen_demo(void);
+void kinematics_demo(void);
+void dynamics_demo(void);
+
+
+int main(void)
+{
+   cout << "=====================================================\n";
+   cout << " ROBOOP -- A robotics object oriented package in C++ \n";;
+   cout << " DEMO program \n";
+   cout << "=====================================================\n";
+   cout << "\n";
+
+   homogen_demo();
+   kinematics_demo();
+   dynamics_demo();
+
+   return(0);
+}
+
+
+void homogen_demo(void)
+{
+   ColumnVector p1(3), p2(3), p3(3);
+   Real ott[] = {1.0,2.0,3.0};
+   Real tto[] = {3.0,2.0,1.0};
+
+   cout << "\n";
+   cout << "=====================================================\n";
+   cout << "Homogeneous transformations\n";
+   cout << "=====================================================\n";
+   cout << "\n";
+   cout << "Translation of [1;2;3]\n";
+   p1 << ott;
+   cout << setw(7) << setprecision(3) << trans(p1);
+   cout << "\n";
+   cout << "\n";
+   cout << "Rotation of pi/6 around axis X\n";
+   cout << setw(7) << setprecision(3) << rotx(M_PI/6);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Rotation of pi/8 around axis Y\n";
+   cout << setw(7) << setprecision(3) << roty(M_PI/8);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Rotation of pi/3 around axis Z\n";
+   cout << setw(7) << setprecision(3) << rotz(M_PI/3);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Rotation of pi/3 around axis [1;2;3]\n";
+   cout << setw(7) << setprecision(3) << rotk(M_PI/3,p1);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Rotation of pi/6 around line [1;2;3] -- [3;2;1]\n";
+   p2 << tto;
+   cout << setw(7) << setprecision(3) << rotd(M_PI/3,p1,p2);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Roll Pitch Yaw Rotation [1;2;3]\n";
+   cout << setw(7) << setprecision(3) << rpy(p1);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Euler ZXZ Rotation [3;2;1]\n";
+   cout << setw(7) << setprecision(3) << eulzxz(p2);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Inverse of Rotation around axis\n";
+   cout << setw(7) << setprecision(3) << irotk(rotk(M_PI/3,p1));
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Inverse of Roll Pitch Yaw Rotation\n";
+   cout << setw(7) << setprecision(3) << irpy(rpy(p1));
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Inverse of Euler ZXZ Rotation\n";
+   cout << setw(7) << setprecision(3) << ieulzxz(eulzxz(p2));
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Cross product between [1;2;3] and [3;2;1]\n";
+   cout << setw(7) << setprecision(3) << CrossProduct(p1,p2);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Rotation matrix from quaternion\n";
+   ColumnVector axis(3); axis(1)=axis(2)=0; axis(3)=1.0;
+   Quaternion q(M_PI/4, axis);
+   cout << setw(7) << setprecision(3) << q.R();
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Transformation matrix from quaternion\n";
+   cout << setw(7) << setprecision(3) << q.T();
+
+   cout << "\n";
+   cout << "Quaternion from rotation matrix\n";
+   Quaternion qq(q.R());
+   cout << setw(7) << setprecision(3) << qq.s() << endl;
+   cout << setw(7) << setprecision(3) << qq.v() << endl;
+   cout << "\n";
+
+   cout << "\n";
+   cout << "Quaternion from transformation matrix\n";
+   qq = Quaternion(q.T());
+   cout << setw(7) << setprecision(3) << qq.s() << endl;
+   cout << setw(7) << setprecision(3) << qq.v() << endl;
+}
+
+const Real RR_data[] =
+   {0.0, 0.0, 0.0, 1.0, 0.0, 2.0,-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1666666, 0.0, 0.1666666,
+    0.0, 0.0, 0.0, 1.0, 0.0, 1.0,-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0833333, 0.0, 0.0833333};
+const Real RR_data_mdh[] =
+   {0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1666666, 0.0, 0.1666666,
+    0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0833333, 0.0, 0.0833333};
+const Real RR_data_mdh_min_para[] =
+   {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.666666,
+    0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.0, 0.0, 0.3333333};
+
+const Real RP_data[] =
+   {0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0,
+    1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,-1.0, 0.0833333, 0.0, 0.0, 0.0833333, 0.0, 0.0833333};
+const Real PUMA560_data[] =
+   {0.0, 0.0, 0.0, 0.0, M_PI/2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.35, 0.0, 0.0,
+    0.0, 0.0, 0.0, 0.4318, 0.0, 17.4, -0.3638, 0.006, 0.2275, 0.13, 0.0, 0.0, 0.524, 0.0, 0.539,
+    0.0, 0.0, 0.15005, 0.0203, -M_PI/2.0, 4.8, -0.0203, -0.0141, 0.07, 0.066, 0.0, 0.0, 0.086, 0.0, 0.0125,
+    0.0, 0.0, 0.4318, 0.0, M_PI/2.0, 0.82, 0.0, 0.019, 0.0, 0.0018, 0.0, 0.0, 0.0013, 0.0, 0.0018,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 0.34, 0.0, 0.0, 0.0, 0.0003, 0.0, 0.0, 0.0004, 0.0, 0.0003,
+    0.0, 0.0, 0.0, 0.0, 0.0, 0.09, 0.0, 0.0, 0.032, 0.00015, 0.0, 0.0, 0.00015, 0.0, 0.00004};
+const Real PUMA560_motor[] =
+   {200e-6, -62.6111, 1.48e-3, (.395 +.435)/2, /* using + and - directions average */
+    200e-6, 107.815, .817e-3, (.126 + .071)/2,
+    200e-6, -53.7063, 1.38e-3, (.132	+ .105)/2,
+    33e-6,   76.0364, 71.2e-6, (11.2e-3 + 16.9e-3)/2,
+    33e-6,   71.923, 82.6e-6, (9.26e-3 + 14.5e-3)/2,
+    33e-6,   76.686, 36.7e-6, (3.96e-3 + 10.5e-3)/2};
+
+const Real STANFORD_data[] =
+   {0.0, 0.0, 0.4120, 0.0, -M_PI/2, 9.29, 0.0, 0.0175, -0.1105, 0.276, 0.0, 0, 0.255, 0.0, 0.071,
+    0.0, 0.0, 0.1540, 0.0, M_PI/2.0, 5.01, 0.0, -1.054, 0.0, 0.108, 0.0, 0.0, 0.018, 0.0, 0.1,
+    1.0, -M_PI/2.0, 0.0, 0.0, 0.0, 4.25, 0.0, 0.0, -6.447, 2.51, 0.0, 0.0, 2.51, 0.0, 0.006,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 1.08, 0.0, 0.092, -0.054, 0.002, 0.0, 0.0, 0.001, 0.0, 0.001,
+    0.0, 0.0, 0.0, 0.0,  M_PI/2.0, 0.63, 0.0, 0.0, 0.566, 0.003, 0.0, 0.0, 0.003, 0.0, 0.0004,
+    0.0, 0.0, 0.2630, 0.0, 0.0, 0.51, 0.0, 0.0, 1.5540, 0.013, 0.0, 0.0, 0.013, 0.0, 0.0003};
+
+Robot robot;
+Matrix K;
+ColumnVector q0;
+
+ReturnMatrix xdot(Real t, const Matrix & x)
+{
+   int ndof;
+   ColumnVector q, qp, qpp; /* position, velocities and accelerations */
+   ColumnVector tau, dx;              /* torque and state space error */
+   Matrix xd;
+
+   ndof = robot.get_dof();                             /* get the # of dof  */
+   q = x.SubMatrix(1,ndof,1,1);               /* position, velocities */
+   qp = x.SubMatrix(ndof+1,2*ndof,1,1);          /* from state vector */
+   qpp = ColumnVector(ndof);
+   qpp = 0.0;                               /* set the vector to zero */
+   //   tau = robot.torque(q0,qpp,qpp); /* compute the gravity torque */
+   tau = ColumnVector(ndof);
+   tau = 0.0;
+
+   dx = (q-q0) & qp;       /* compute dx using vertical concatenation */
+   tau = tau - K*dx;                           /* feedback correction */
+   qpp = robot.acceleration(q, qp, tau);              /* acceleration */
+   xd = qp & qpp;                          /* state vector derivative */
+
+   xd.Release(); return xd;
+}
+
+void kinematics_demo(void)
+{
+   Matrix initrob(2,15), Tobj;
+   ColumnVector qs, qr;
+   int dof = 0;
+   int i;
+
+   cout << "\n";
+   cout << "=====================================================\n";
+   cout << "Robot RR kinematics\n";
+   cout << "=====================================================\n";
+   initrob << RR_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "   type     theta      d        a      alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot.set_q(qr);
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to base frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to tool frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian(qr.Nrows());
+   cout << "\n";
+   for (i = 1; i <= qr.Nrows(); i++) {
+      cout << "Robot position partial derivative with respect to joint " << i << " \n";
+      cout << setw(7) << setprecision(3) << robot.dTdqi(i);
+      cout << "\n";
+   }
+   Tobj = robot.kine();
+   qs = ColumnVector(dof);
+   qs = M_PI/16.0;
+   robot.set_q(qs);
+   cout << "Robot inverse kinematics\n";
+   cout << "  q start  q final  q real\n";
+   cout << setw(7) << setprecision(3) << (qs | robot.inv_kin(Tobj) | qr);
+   cout << "\n";
+   cout << "\n";
+
+   cout << "=====================================================\n";
+   cout << "Robot RP kinematics\n";
+   cout << "=====================================================\n";
+   initrob << RP_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   robot.set_q(M_PI/4.0,1);
+   robot.set_q(4.0,2);
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to base frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian();
+   cout << "\n";
+   qr = robot.get_q();
+   cout << "Robot Jacobian w/r to tool frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian(qr.Nrows());
+   cout << "\n";
+   for (i = 1; i <= qr.Nrows(); i++) {
+      cout << "Robot position partial derivative with respect to joint " << i << " \n";
+      cout << setw(7) << setprecision(3) << robot.dTdqi(i);
+      cout << "\n";
+   }
+   Tobj = robot.kine();
+   robot.set_q(M_PI/16.0,1);
+   robot.set_q(1.0,2);
+   qs = robot.get_q();
+   cout << "Robot inverse kinematics\n";
+   cout << " q start q final q real\n";
+   cout << setw(7) << setprecision(3) << (qs | robot.inv_kin(Tobj) | qr);
+   cout << "\n";
+   cout << "\n";
+
+   cout << "=====================================================\n";
+   cout << "Robot PUMA560 kinematics\n";
+   cout << "=====================================================\n";
+   robot = Robot("conf/puma560_dh.conf", "PUMA560_DH");
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot.set_q(qr);
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to base frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to tool frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian(qr.Nrows());
+   cout << "\n";
+   for (i = 1; i <= qr.Nrows(); i++) {
+      cout << "Robot position partial derivative with respect to joint " << i << " \n";
+      cout << setw(7) << setprecision(3) << robot.dTdqi(i);
+      cout << "\n";
+   }
+   Tobj = robot.kine();
+   qs = ColumnVector(dof);
+   qs = 1.0;
+   qs(1) = M_PI/16.0;
+   robot.set_q(qs);
+   cout << "Robot inverse kinematics\n";
+   cout << " q start q final q real\n";
+   cout << setw(7) << setprecision(3) << (qs | robot.inv_kin(Tobj) | qr);
+   cout << "\n";
+   cout << "\n";
+   cout << "=====================================================\n";
+   cout << "Robot STANFORD kinematics\n";
+   cout << "=====================================================\n";
+   initrob = Matrix(6,15);
+   initrob << STANFORD_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot.set_q(qr);
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot position\n";
+   cout << setw(7) << setprecision(3) << robot.kine();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to base frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian();
+   cout << "\n";
+   cout << "Robot Jacobian w/r to tool frame\n";
+   cout << setw(7) << setprecision(3) << robot.jacobian(qr.Nrows());
+   cout << "\n";
+   for (i = 1; i <= qr.Nrows(); i++) {
+      cout << "Robot position partial derivative with respect to joint " << i << " \n";
+      cout << setw(7) << setprecision(3) << robot.dTdqi(i);
+      cout << "\n";
+   }
+   Tobj = robot.kine();
+   qs = ColumnVector(dof);
+   qs = 1.0;
+   qs(1) = M_PI/16.0;
+   robot.set_q(qs);
+   cout << "Robot inverse kinematics\n";
+   cout << " q start q final q real\n";
+   cout << setw(7) << setprecision(3) << (qs | robot.inv_kin(Tobj) | qr);
+   cout << "\n";
+   cout << "\n";
+}
+
+void dynamics_demo(void)
+{
+   int nok, nbad, dof = 0;
+   Matrix initrob(2,15), Tobj, xout;
+   ColumnVector qs, qr;
+   RowVector tout;
+   int i;
+
+   cout << "\n";
+   cout << "=====================================================\n";
+   cout << "Robot RR dynamics\n";
+   cout << "=====================================================\n";
+   initrob << RR_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot D-H inertial parameters\n";
+   cout << "  mass     cx       cy      cz     Ixx     Ixy     Ixz     Iyy     Iyz     Izz\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,6,15);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot Inertia matrix\n";
+   cout << setw(7) << setprecision(3) << robot.inertia(robot.get_q());
+   cout << "\n";
+
+   K = Matrix(dof,2*dof);
+   K = 0.0;
+   K(1,1) = K(2,2) = 25.0;      /* K = [25I 7.071I ] */
+   K(1,3) = K(2,4) = 7.071;
+   cout << "Feedback gain matrix K\n";
+   cout << setw(7) << setprecision(3) << K;
+   cout << "\n";
+   q0 = ColumnVector(dof);
+   q0 = M_PI/4.0;
+   qs = ColumnVector(2*dof);
+   qs = 0.0;
+
+   cout << " time     ";
+   for(i = 1; i <= dof; i++)
+      cout <<"q" << i << "      ";
+   for(i = 1; i <= dof; i++)
+      cout <<"qp" << i << "     ";
+   cout << endl;
+
+   /*   Runge_Kutta4(xdot, qs, 0.0, 4.0, 160, tout, xout);
+   replaced by adaptive step size */
+   odeint(xdot, qs, 0.0, 4.0, 1e-4,0.1, 1e-12, nok, nbad, tout, xout, 0.05);
+   cout << setw(7) << setprecision(3) << (tout & xout).t();
+   cout << "\n";
+   cout << "\n";
+
+
+   set_plot2d("Robot joints position", "time (sec)", "q(i) (rad)", "q", POINTS,
+              tout, xout, 1, dof);
+
+   /* uncomment the following two lines to obtain a
+      ps file of the graph */
+   /*   plotposition.addcommand("set term post");
+      plotposition.addcommand("set output \"demo.ps\"");*/
+
+   set_plot2d("Robot joints velocity", "time (sec)", "qp(i) (rad/s)", "qp", POINTS,
+              tout, xout, dof+1, 2*dof);
+
+
+   cout << "=====================================================\n";
+   cout << "Robot RP dynamics\n";
+   cout << "=====================================================\n";
+   initrob << RP_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot D-H inertial parameters\n";
+   cout << "  mass     cx       cy      cz     Ixx     Ixy     Ixz     Iyy     Iyz     Izz\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,6,15);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot Inertia matrix\n";
+   cout << setw(7) << setprecision(3) << robot.inertia(robot.get_q());
+   cout << "\n";
+   cout << "\n";
+
+   cout << "=====================================================\n";
+   cout << "Robot PUMA560 dynamics\n";
+   cout << "=====================================================\n";
+   initrob = Matrix(6,15);
+   initrob << PUMA560_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot D-H inertial parameters\n";
+   cout << "  mass     cx       cy      cz     Ixx     Ixy     Ixz     Iyy     Iyz     Izz\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,6,15);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot Inertia matrix\n";
+   cout << setw(8) << setprecision(4) << robot.inertia(robot.get_q());
+   cout << "\n";
+   qs = ColumnVector(dof);
+   qr = ColumnVector(dof);
+   qs =0.0;
+   qr =0.0;
+   cout << "Robot Torque\n";
+   cout << setw(8) << setprecision(4) << robot.torque(robot.get_q(),qs,qr);
+   cout << "\n";
+   cout << "Robot acceleration\n";
+   cout << setw(8) << setprecision(4) << robot.acceleration(robot.get_q(),qs,qr);
+   cout << "\n";
+
+   cout << "\n";
+   cout << "=====================================================\n";
+   cout << "Robot STANFORD dynamics\n";
+   cout << "=====================================================\n";
+   initrob = Matrix(6,15);
+   initrob << STANFORD_data;
+   robot = Robot(initrob);
+   dof = robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot D-H inertial parameters\n";
+   cout << "  mass     cx       cy      cz     Ixx     Ixy     Ixz     Iyy     Iyz     Izz\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,6,15);
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot Inertia matrix\n";
+   cout << setw(7) << setprecision(3) << robot.inertia(robot.get_q());
+   cout << "\n";
+   cout << "\n";
+
+   cout << "=====================================================\n";
+   cout << "Robot PUMA560 with motors dynamics\n";
+   cout << "=====================================================\n";
+   initrob = Matrix(6,15);
+   initrob << PUMA560_data;
+   Matrix initrobm = Matrix(6,4);
+   initrobm << PUMA560_motor;
+   robot = Robot(initrob,initrobm);
+   dof =robot.get_dof();
+   cout << "\n";
+   cout << "Robot D-H parameters\n";
+   cout << "  type    theta     d       a     alpha\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,1,5);
+   cout << "\n";
+   cout << "Robot D-H inertial parameters\n";
+   cout << "  mass     cx       cy      cz     Ixx     Ixy     Ixz     Iyy     Iyz     Izz\n";
+   cout << setw(7) << setprecision(3) << initrob.SubMatrix(1,dof,6,15);
+   cout << "\n";
+   cout << "Robot motors inertia, gear ratio, viscous and Coulomb friction coefficients\n";
+   cout << "  Im       Gr       B       Cf\n";
+   cout << setw(7) << setprecision(3) << initrobm;
+   cout << "\n";
+   cout << "Robot joints variables\n";
+   cout << setw(7) << setprecision(3) << robot.get_q();
+   cout << "\n";
+   cout << "Robot Inertia matrix\n";
+   cout << setw(8) << setprecision(4) << robot.inertia(robot.get_q());
+   cout << "\n";
+   qs = ColumnVector(dof);
+   qr = ColumnVector(dof);
+   qs =0.0;
+   qr =0.0;
+   robot.set_q(qs);
+   cout << "Robot Torque\n";
+   cout << setw(8) << setprecision(4) << robot.torque(robot.get_q(),qs,qr);
+   cout << "\n";
+   cout << "Robot acceleration\n";
+   cout << setw(8) << setprecision(4) << robot.acceleration(robot.get_q(),qs,qr);
+   cout << "\n";
+}
Index: Motion/roboop/extra/demo_2dof_pd.cpp
===================================================================
RCS file: Motion/roboop/extra/demo_2dof_pd.cpp
diff -N Motion/roboop/extra/demo_2dof_pd.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/demo_2dof_pd.cpp	14 Jul 2004 02:29:41 -0000	1.1
@@ -0,0 +1,137 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 2002-2004  Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Etienne Lachance
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+*/
+/*! 
+  @file demo_2dof_pd.cpp
+  @brief A demo file.
+
+  This demo file shows a two degree of freedom robots controller by
+  a pd controller. The robot is define by the file "conf/rr_dh.conf", 
+  while the controller is defined by the file "conf/pd_2dof.conf". The
+  desired joint trajectory is defined by the file "conf/q_2dof.dat";
+*/
+
+//! @brief RCS/CVS version.
+static const char rcsid[] = "$Id: demo_2dof_pd.cpp,v 1.1 2004/07/14 02:29:41 ejt Exp $";
+
+#include "controller.h"
+#include "control_select.h"
+#include "dynamics_sim.h"
+#include "gnugraph.h"
+#include "robot.h"
+#include "trajectory.h"
+
+#ifdef use_namespace
+using namespace ROBOOP;
+#endif
+
+/*!
+  @class New_dynamics
+  @brief This is an example of customize Dynamics class.
+
+  This class enherite from Dynamics class. At every time
+  frame the new virtual plot functions record the current time
+  and the robot joints positions. The data can then be
+  used to create a plot.
+*/
+class New_dynamics: public Dynamics
+{
+public:
+  New_dynamics(Robot_basic *robot_);
+  virtual void plot();
+
+  Robot_basic *robot;    /**< Robot_basic pointer.         */
+  bool first_pass_plot;  /**< First time in plot function. */
+  RowVector tout;        /**< Output time vector.          */
+  Matrix xout;           /**< Output state vector.         */
+  int i;                 /**< Temporary index.             */
+};
+
+/*! 
+  @fn New_dynamics::New_dynamics(Robot_basic *robot)
+  @brief Constructor
+*/
+New_dynamics::New_dynamics(Robot_basic *robot_): Dynamics(robot_)
+{
+  robot = robot_;
+  first_pass_plot = true;
+  i = 1;
+}
+
+/*! 
+  @fn void New_dynamics::plot()
+  @brief Customize plot function.
+
+  Record the time (tout) and the joints positions (xout). This
+  member function is call by the member function xdot.
+*/
+void New_dynamics::plot()
+{
+  if(first_pass_plot)
+    {
+      xout = Matrix(x.Nrows(),(int)(nsteps*(tf_cont-to)+1)*x.Ncols());
+      xout.SubMatrix(1,x.Nrows(),1,x.Ncols()) = x;
+      tout = RowVector((int)(nsteps*(tf_cont-to)+1));
+      tout(1) = to;
+      i = 0;
+      first_pass_plot = false;
+    }
+
+  if(robot)
+    {
+      tout(i+1) = time;
+      xout.SubMatrix(1,x.Nrows(),i*x.Ncols()+1,(i+1)*x.Ncols()) = x;
+      i++;
+    }
+}
+
+
+int main()
+{
+  
+  Robot robot("conf/rr_dh.conf", "rr_dh");
+
+  Trajectory_Select path("conf/q_2dof.dat");
+  Control_Select control("conf/pd_2dof.conf");
+
+  New_dynamics dynamics(&robot);
+
+  dynamics.set_controller(control);
+  dynamics.set_trajectory(path);
+  dynamics.set_time_frame(500);
+
+  dynamics.Runge_Kutta4();
+
+  set_plot2d("Robot joints position", "time (sec)", "q(i) (rad)", "q", POINTS,
+	     dynamics.tout, dynamics.xout, 1, 2);
+ 
+   return(0);
+}
+
+
Index: Motion/roboop/extra/makefile.gcc
===================================================================
RCS file: Motion/roboop/extra/makefile.gcc
diff -N Motion/roboop/extra/makefile.gcc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/makefile.gcc	2 Jul 2004 00:19:33 -0000	1.2
@@ -0,0 +1,143 @@
+# Roboop Makefile for GNU g++
+# $Id: makefile.gcc,v 1.2 2004/07/02 00:19:33 ejt Exp $
+
+CC = g++
+
+# uncomment the -fno-const-strings in the next line for gcc 2.95.2
+CFLAGS = -O -I ./source -I ./newmat -Wall -D_REENTRANT -pthread#-fno-const-strings
+LIBS = -L./ -lroboop -lnewmat -lm -pthread
+AR = ar
+
+%.o : source/%.cpp
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+%.o : newmat/%.cpp
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+All: rtest demo bench libnewmat.a libroboop.a
+
+Deprtest =  rtest.o libroboop.a libnewmat.a
+rtest : $(Deprtest)
+	$(CC) $< -o $@ $(LIBS)
+rtest.o :  source/rtest.cpp source/utils.h source/robot.h
+
+Depdemo    = demo.o libroboop.a libnewmat.a
+demo: $(Depdemo)
+	$(CC) $< -o  $@ $(LIBS)
+demo.o :  source/demo.cpp source/quaternion.h source/gnugraph.h source/utils.h source/robot.h
+
+Deprobooplib = \
+   gnugraph.o   comp_dq.o   comp_dqp.o   delta_t.o \
+   dynamics.o   homogen.o   kinemat.o    robot.o   \
+   sensitiv.o   utils.o     quaternion.o config.o  \
+   trajectory.o clik.o      impedance.o  invkine.o
+
+libroboop.a : $(Deprobooplib)
+	rm -f $@
+	$(AR) rc $@ $(Deprobooplib)
+
+impedance.o: source/impedance.cpp source/impedance.h
+
+trajectory.o: source/trajectory.cpp source/trajectory.h
+
+clik.o :  source/clik.cpp source/clik.h source/utils.h source/robot.h
+
+robot.o :  source/robot.cpp source/utils.h source/robot.h
+
+config.o : source/config.cpp source/config.h source/utils.h
+
+quaternion.o : source/quaternion.cpp source/quaternion.h
+
+gnugraph.o :  source/gnugraph.cpp source/gnugraph.h source/utils.h source/robot.h
+
+comp_dq.o :  source/comp_dq.cpp source/utils.h source/robot.h
+
+comp_dqp.o :  source/comp_dqp.cpp source/utils.h source/robot.h
+
+delta_t.o :  source/delta_t.cpp source/utils.h source/robot.h
+
+dynamics.o :  source/dynamics.cpp source/utils.h source/robot.h
+
+homogen.o :  source/homogen.cpp source/utils.h source/robot.h
+
+invkine.o :  source/invkine.cpp source/utils.h source/robot.h
+
+kinemat.o :  source/kinemat.cpp source/utils.h source/robot.h
+
+sensitiv.o :  source/sensitiv.cpp source/utils.h source/robot.h
+
+utils.o :  source/utils.cpp source/utils.h source/robot.h
+
+Depnewmatlib = \
+   bandmat.o    cholesky.o   evalue.o     fft.o\
+   hholder.o    jacobi.o     myexcept.o   newmat1.o\
+   newmat2.o    newmat3.o    newmat4.o    newmat5.o\
+   newmat6.o    newmat7.o    newmat8.o    newmat9.o\
+   newmatex.o   newmatnl.o   newmatrm.o   solution.o\
+   sort.o       submat.o     svd.o        newfft.o
+
+libnewmat.a: $(Depnewmatlib)
+	rm -f $@
+	$(AR) rc $@ $(Depnewmatlib)
+
+bandmat.o :  newmat/bandmat.cpp
+
+cholesky.o :  newmat/cholesky.cpp
+
+evalue.o :  newmat/evalue.cpp
+
+fft.o :  newmat/fft.cpp
+
+newfft.o :  newmat/newfft.cpp
+
+hholder.o :  newmat/hholder.cpp
+
+jacobi.o :  newmat/jacobi.cpp
+
+myexcept.o :  newmat/myexcept.cpp
+
+newmat1.o :  newmat/newmat1.cpp
+
+newmat2.o :  newmat/newmat2.cpp
+
+newmat3.o :  newmat/newmat3.cpp
+
+newmat4.o :  newmat/newmat4.cpp
+
+newmat5.o :  newmat/newmat5.cpp
+
+newmat6.o :  newmat/newmat6.cpp
+
+newmat7.o :  newmat/newmat7.cpp
+
+newmat8.o :  newmat/newmat8.cpp
+
+newmat9.o :  newmat/newmat9.cpp
+
+newmatex.o :  newmat/newmatex.cpp
+
+newmatnl.o :  newmat/newmatnl.cpp
+
+newmatrm.o :  newmat/newmatrm.cpp
+
+solution.o :  newmat/solution.cpp
+
+sort.o :  newmat/sort.cpp
+
+submat.o :  newmat/submat.cpp
+
+svd.o :  newmat/svd.cpp
+
+Depbench =  bench.o libroboop.a libnewmat.a
+
+bench : $(Depbench)
+	$(CC) $< -o $@ $(LIBS)
+
+bench.o :  source/bench.cpp source/utils.h source/robot.h
+
+clean:
+	rm *.o *.a
+
+veryclean: clean
+	rm rtest bench demo
+
Index: Motion/roboop/extra/matlabtest.m
===================================================================
RCS file: Motion/roboop/extra/matlabtest.m
diff -N Motion/roboop/extra/matlabtest.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/matlabtest.m	16 Jun 2004 21:50:00 -0000	1.1
@@ -0,0 +1,60 @@
+%
+%
+clear
+%
+a = transl([1;2;3]);
+b = rotx(pi/6);
+c = roty(pi/6);
+d = rotz(pi/6);
+e = rpy2tr([3;2;1]);
+f = rotvec([1;2;3],pi/2);
+
+q_ = quaternion([0 0 1], pi/4);
+g  = q_.r;
+q_ = quaternion([pi/4, pi/6, pi/8, 1]);
+qu_= unit(q_);
+h  = qu_.r;    % Rotation Matrix from quaternion
+i  = qu_.t;    % Transformation "            "
+q_ = quaternion(h);
+j  = [q_.s q_.v];
+q_ = quaternion(i);
+k  = [q_.s q_.v];
+
+% -------------- R O B O T -----------------
+
+clear q_;
+q_   = [pi/4 pi/4 pi/4 pi/4 pi/4 pi/4];
+qd_  = q_;
+qdd_ = q_;
+run puma560_no_motor;
+l = fkine(p560, q_);
+m = jacob0(p560, q_);
+n = jacobn(p560, q_);
+o = rne_dh(p560, q_, qd_, qdd_);
+p = inertia(p560, q_);
+clear p560;
+run puma560_motor;
+q = rne_dh(p560, q_, qd_, qdd_);
+
+run stanford_no_motor;
+r = fkine(stanf, q_);
+s = jacob0(stanf, q_);
+t = jacobn(stanf, q_);
+u = rne_dh(stanf, q_, qd_, qdd_);
+g_ = [0;0;9.81];
+f_ = [10;5;7;11;22;33];
+v = rne_dh(stanf, q_, qd_, qdd_, g_, f_);
+w = inertia(stanf, q_);
+
+run puma560akb_no_motor;
+x = fkine(p560m, q_);
+y = jacob0(p560m, q_);
+z = jacobn(p560m, q_);
+aa = rne_mdh(p560m, q_, qd_, qdd_);
+bb= inertia(p560m, q_);
+clear p560m;
+run puma560akb_motor;
+cc = rne_mdh(p560m, q_, qd_, qdd_);
+dd = rne_mdh(p560m, q_, qd_, qdd_, g_, f_);
+
+save ../source/test.txt -ascii -double a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd
Index: Motion/roboop/extra/puma560_motor.m
===================================================================
RCS file: Motion/roboop/extra/puma560_motor.m
diff -N Motion/roboop/extra/puma560_motor.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/puma560_motor.m	14 Jul 2004 02:29:41 -0000	1.2
@@ -0,0 +1,159 @@
+%PUMA560 Load kinematic and dynamic data for a Puma 560 manipulator
+%
+%	PUMA560
+%
+% Defines the object 'p560' in the current workspace which describes the 
+% kinematic and dynamic % characterstics of a Unimation Puma 560 manipulator
+% using standard DH conventions.
+% The model includes armature inertia and gear ratios.
+%
+% Also define the vector qz which corresponds to the zero joint
+% angle configuration, qr which is the vertical 'READY' configuration,
+% and qstretch in which the arm is stretched out in the X direction.
+%
+% See also: ROBOT, PUMA560AKB, STANFORD, TWOLINK.
+
+%
+% Notes:
+%    - the value of m1 is given as 0 here.  Armstrong found no value for it
+% and it does not appear in the equation for tau1 after the substituion
+% is made to inertia about link frame rather than COG frame.
+% updated:
+% 2/8/95  changed D3 to 150.05mm which is closer to data from Lee, AKB86 and Tarn
+%  fixed errors in COG for links 2 and 3
+% 29/1/91 to agree with data from Armstrong etal.  Due to their use
+%  of modified D&H params, some of the offsets Ai, Di are
+%  offset, and for links 3-5 swap Y and Z axes.
+% 14/2/91 to use Paul's value of link twist (alpha) to be consistant
+%  with ARCL.  This is the -ve of Lee's values, which means the
+%  zero angle position is a righty for Paul, and lefty for Lee.
+%  Note that gravity load torque is the motor torque necessary
+%  to keep the joint static, and is thus -ve of the gravity
+%  caused torque.
+%
+% 8/95 fix bugs in COG data for Puma 560. This led to signficant errors in
+%  inertia of joint 1. 
+% $Log: puma560_motor.m,v $
+% Revision 1.2  2004/07/14 02:29:41  ejt
+% update to roboop version 1.20
+%
+% Revision 1.2  2004/07/06 02:16:36  gourdeau
+% doxy etc
+%
+% Revision 1.1  2004/05/12 13:34:37  elachance
+% Initial revision
+%
+% Revision 1.1  2003/02/06 04:31:36  gourdeau
+% 1er rev Etienne L.
+%
+% Revision 1.1  2002/12/17 02:31:55  elachance
+% Initial revision
+%
+% Revision 1.3  2002/04/01 11:47:16  pic
+% General cleanup of code: help comments, see also, copyright, remnant dh/dyn
+% references, clarification of functions.
+%
+% $Revision: 1.2 $
+
+% Copyright (C) 1993-2002, by Peter I. Corke
+
+clear L
+
+L{1} = link([pi/2 0	0	0	0], 'standard');
+L{2} = link([ 0 	.4318	0	0	0], 'standard');
+L{3} = link([-pi/2 .0203	0      .15005	0], 'standard');
+L{4} = link([pi/2 0	0	.4318	0], 'standard');
+L{5} = link([-pi/2 0	0	0	0], 'standard');
+L{6} = link([0 	0	0	0	0], 'standard');
+
+%L{1} = link([pi/2 0	0	0	0], 'standard');
+%L{2} = link([ 0 	.4318	0	0	0], 'standard');
+%L{3} = link([-pi/2 .0203	0	.15005	0], 'standard');
+%L{4} = link([pi/2 0	0	.4318	0], 'standard');
+%L{5} = link([-pi/2 0	0	0	0], 'standard');
+%L{6} = link([0 	0	0	0	0], 'standard');
+
+
+L{1}.m = 0;
+L{2}.m = 17.4;
+L{3}.m = 4.8;
+L{4}.m = 0.82;
+L{5}.m = 0.34;
+L{6}.m = .09;
+
+L{1}.r = [ 0    0	   0 ];
+L{2}.r = [ -.3638  .006    .2275];
+L{3}.r = [ -.0203  -.0141  .070];
+L{4}.r = [ 0    .019    0];
+L{5}.r = [ 0    0	   0];
+L{6}.r = [ 0    0	   .032];
+
+L{1}.I = [  0	 0.35	 0	 0	 0	 0];
+L{2}.I = [  .13	 .524	 .539	 0	 0	 0];
+L{3}.I = [   .066  .086	 .0125   0	 0	 0];
+L{4}.I = [  1.8e-3  1.3e-3  1.8e-3  0	 0	 0];
+L{5}.I = [  .3e-3   .4e-3   .3e-3   0	 0	 0];
+L{6}.I = [  .15e-3  .15e-3  .04e-3  0	 0	 0];
+
+L{1}.Jm =  200e-6;
+L{2}.Jm =  200e-6;
+L{3}.Jm =  200e-6;
+L{4}.Jm =  33e-6;
+L{5}.Jm =  33e-6;
+L{6}.Jm =  33e-6;
+
+%L{1}.G =  1.0;
+%L{2}.G =  1.0;
+%L{3}.G =  1.0;
+%L{4}.G =  1.0;
+%L{5}.G =  1.0;
+%L{6}.G =  1.0;
+
+L{1}.G =  -62.6111;
+L{2}.G =  107.815;
+L{3}.G =  -53.7063;
+L{4}.G =  76.0364;
+L{5}.G =  71.923;
+L{6}.G =  76.686;
+
+% viscous friction (motor referenced)
+L{1}.B =   1.48e-3;
+L{2}.B =   .817e-3;
+L{3}.B =    1.38e-3;
+L{4}.B =   71.2e-6;
+L{5}.B =   82.6e-6;
+L{6}.B =   36.7e-6;
+
+% Coulomb friction (motor referenced)
+L{1}.Tc = [ 0.0  0.0];
+L{2}.Tc = [ 0.0  0.0];
+L{3}.Tc = [ 0.0  0.0];
+L{4}.Tc = [ 0.0  0.0];
+L{5}.Tc = [ 0.0  0.0];
+L{6}.Tc = [ 0.0  0.0];
+
+%L{1}.Tc = [ .395	-.435];
+%L{2}.Tc = [ .126	-.071];
+%L{3}.Tc = [ .132	-.105];
+%L{4}.Tc = [ 11.2e-3 -16.9e-3];
+%L{5}.Tc = [ 9.26e-3 -14.5e-3];
+%L{6}.Tc = [ 3.96e-3 -10.5e-3];
+
+
+%
+% some useful poses
+%
+qz = [0 0 0 0 0 0]; % zero angles, L shaped pose
+qr = [0 pi/2 -pi/2 0 0 0]; % ready pose, arm up
+qstretch = [0 0 -pi/2 0 0 0];
+
+p560 = robot(L, 'Puma 560', 'Unimation', 'params of 8/95');
+clear L
+p560.name = 'Puma 560';
+p560.manuf = 'Unimation';
+
+
+
+
+
+
Index: Motion/roboop/extra/puma560_no_motor.m
===================================================================
RCS file: Motion/roboop/extra/puma560_no_motor.m
diff -N Motion/roboop/extra/puma560_no_motor.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/puma560_no_motor.m	14 Jul 2004 02:29:41 -0000	1.2
@@ -0,0 +1,142 @@
+%PUMA560 Load kinematic and dynamic data for a Puma 560 manipulator
+%
+%	PUMA560
+%
+% Defines the object 'p560' in the current workspace which describes the 
+% kinematic and dynamic % characterstics of a Unimation Puma 560 manipulator
+% using standard DH conventions.
+% The model includes armature inertia and gear ratios.
+%
+% Also define the vector qz which corresponds to the zero joint
+% angle configuration, qr which is the vertical 'READY' configuration,
+% and qstretch in which the arm is stretched out in the X direction.
+%
+% See also: ROBOT, PUMA560AKB, STANFORD, TWOLINK.
+
+%
+% Notes:
+%    - the value of m1 is given as 0 here.  Armstrong found no value for it
+% and it does not appear in the equation for tau1 after the substituion
+% is made to inertia about link frame rather than COG frame.
+% updated:
+% 2/8/95  changed D3 to 150.05mm which is closer to data from Lee, AKB86 and Tarn
+%  fixed errors in COG for links 2 and 3
+% 29/1/91 to agree with data from Armstrong etal.  Due to their use
+%  of modified D&H params, some of the offsets Ai, Di are
+%  offset, and for links 3-5 swap Y and Z axes.
+% 14/2/91 to use Paul's value of link twist (alpha) to be consistant
+%  with ARCL.  This is the -ve of Lee's values, which means the
+%  zero angle position is a righty for Paul, and lefty for Lee.
+%  Note that gravity load torque is the motor torque necessary
+%  to keep the joint static, and is thus -ve of the gravity
+%  caused torque.
+%
+% 8/95 fix bugs in COG data for Puma 560. This led to signficant errors in
+%  inertia of joint 1. 
+% $Log: puma560_no_motor.m,v $
+% Revision 1.2  2004/07/14 02:29:41  ejt
+% update to roboop version 1.20
+%
+% Revision 1.2  2004/07/06 02:16:36  gourdeau
+% doxy etc
+%
+% Revision 1.1  2004/05/12 13:34:37  elachance
+% Initial revision
+%
+% Revision 1.1  2003/02/06 04:31:36  gourdeau
+% 1er rev Etienne L.
+%
+% Revision 1.1  2002/12/13 04:50:05  elachance
+% Initial revision
+%
+% Revision 1.3  2002/04/01 11:47:16  pic
+% General cleanup of code: help comments, see also, copyright, remnant dh/dyn
+% references, clarification of functions.
+%
+% $Revision: 1.2 $
+
+% Copyright (C) 1993-2002, by Peter I. Corke
+
+clear L
+
+L{1} = link([pi/2 0	0	0	0], 'standard');
+L{2} = link([ 0 	.4318	0	0	0], 'standard');
+L{3} = link([-pi/2 .0203	0      .15005	0], 'standard');
+L{4} = link([pi/2 0	0	.4318	0], 'standard');
+L{5} = link([-pi/2 0	0	0	0], 'standard');
+L{6} = link([0 	0	0	0	0], 'standard');
+
+%L{1} = link([pi/2 0	0	0	0], 'standard');
+%L{2} = link([ 0 	.4318	0	0	0], 'standard');
+%L{3} = link([-pi/2 .0203	0	.15005	0], 'standard');
+%L{4} = link([pi/2 0	0	.4318	0], 'standard');
+%L{5} = link([-pi/2 0	0	0	0], 'standard');
+%L{6} = link([0 	0	0	0	0], 'standard');
+
+
+L{1}.m = 0;
+L{2}.m = 17.4;
+L{3}.m = 4.8;
+L{4}.m = 0.82;
+L{5}.m = 0.34;
+L{6}.m = .09;
+
+L{1}.r = [ 0    0	   0 ];
+L{2}.r = [ -.3638  .006    .2275];
+L{3}.r = [ -.0203  -.0141  .070];
+L{4}.r = [ 0    .019    0];
+L{5}.r = [ 0    0	   0];
+L{6}.r = [ 0    0	   .032];
+
+L{1}.I = [  0	 0.35	 0	 0	 0	 0];
+L{2}.I = [  .13	 .524	 .539	 0	 0	 0];
+L{3}.I = [   .066  .086	 .0125   0	 0	 0];
+L{4}.I = [  1.8e-3  1.3e-3  1.8e-3  0	 0	 0];
+L{5}.I = [  .3e-3   .4e-3   .3e-3   0	 0	 0];
+L{6}.I = [  .15e-3  .15e-3  .04e-3  0	 0	 0];
+
+L{1}.Jm =  0;
+L{2}.Jm =  0;
+L{3}.Jm =  0;
+L{4}.Jm =  0;
+L{5}.Jm =  0;
+L{6}.Jm =  0;
+
+L{1}.G =  0;
+L{2}.G =  0;
+L{3}.G =  0;
+L{4}.G =  0;
+L{5}.G =  0;
+L{6}.G =  0;
+
+% viscous friction (motor referenced)
+L{1}.B =   0;
+L{2}.B =   0;
+L{3}.B =   0;
+L{4}.B =   0;
+L{5}.B =   0;
+L{6}.B =   0;
+
+% Coulomb friction (motor referenced)
+L{1}.Tc = [ 0.0  0.0];
+L{2}.Tc = [ 0.0  0.0];
+L{3}.Tc = [ 0.0  0.0];
+L{4}.Tc = [ 0.0  0.0];
+L{5}.Tc = [ 0.0  0.0];
+L{6}.Tc = [ 0.0  0.0];
+
+
+
+%
+% some useful poses
+%
+qz = [0 0 0 0 0 0]; % zero angles, L shaped pose
+qr = [0 pi/2 -pi/2 0 0 0]; % ready pose, arm up
+qstretch = [0 0 -pi/2 0 0 0];
+
+p560 = robot(L, 'Puma 560', 'Unimation', 'params of 8/95');
+clear L
+p560.name = 'Puma 560';
+p560.manuf = 'Unimation';
+
+
Index: Motion/roboop/extra/puma560akb_motor.m
===================================================================
RCS file: Motion/roboop/extra/puma560akb_motor.m
diff -N Motion/roboop/extra/puma560akb_motor.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/puma560akb_motor.m	14 Jul 2004 02:29:41 -0000	1.2
@@ -0,0 +1,139 @@
+%PUMA560AKB Load kinematic and dynamic data for a Puma 560 manipulator
+%
+%	PUMA560AKB
+%
+% Defines the object 'p560m' in current workspace which describes the 
+% kinematic and dynamic characterstics of a Unimation Puma 560 manipulator 
+% modified DH conventions and using the data and conventions of:
+%
+%	Armstrong, Khatib and Burdick 1986.
+%	"The Explicit Dynamic Model and Inertial Parameters of the Puma 560 Arm"
+%
+% Also define the vector qz which corresponds to the zero joint
+% angle configuration, qr which is the vertical 'READY' configuration,
+% and qstretch in which the arm is stretched out in the X direction.
+%
+% See also: ROBOT, PUMA560, STANFORD, TWOLINK.
+
+% Copyright (C) 1993-2002, by Peter I. Corke
+% CHANGES:
+% 12/01	convert to object format
+% $Log: puma560akb_motor.m,v $
+% Revision 1.2  2004/07/14 02:29:41  ejt
+% update to roboop version 1.20
+%
+% Revision 1.2  2004/07/06 02:16:36  gourdeau
+% doxy etc
+%
+% Revision 1.1  2004/05/12 13:34:37  elachance
+% Initial revision
+%
+% Revision 1.1  2003/02/06 04:31:36  gourdeau
+% 1er rev Etienne L.
+%
+% Revision 1.1  2002/12/17 02:32:22  elachance
+% Initial revision
+%
+% Revision 1.1  2002/12/13 04:50:14  elachance
+% Initial revision
+%
+% Revision 1.3  2002/04/01 11:47:15  pic
+% General cleanup of code: help comments, see also, copyright, remnant dh/dyn
+% references, clarification of functions.
+%
+% $Revision: 1.2 $
+
+clear L
+%            alpha   A     theta    D	sigma
+L{1} = link([0       0       0       0       0], 'mod');
+L{2} = link([-pi/2   0       0       0  0], 'mod');
+L{3} = link([0       0.4318  0      -0.15005 0], 'mod');
+L{4} = link([-pi/2   0.0203 0       -.4318   0], 'mod');
+L{5} = link([pi/2   0       0       0       0], 'mod');
+L{6} = link([-pi/2    0       0       0       0], 'mod');
+
+%L{1} = link([0       0       0       0       0], 'mod');
+%L{2} = link([-pi/2   0       0       0.2435  0], 'mod');
+%L{3} = link([0       0.4318  0       -0.0934 0], 'mod');
+%L{4} = link([pi/2    -0.0203 0       .4331   0], 'mod');
+%L{5} = link([-pi/2   0       0       0       0], 'mod');
+%L{6} = link([pi/2    0       0       0       0], 'mod');
+
+L{1}.m = 0;
+L{2}.m = 17.4;
+L{3}.m = 4.8;
+L{4}.m = 0.82;
+L{5}.m = 0.34;
+L{6}.m = .09;
+
+%         rx      ry      rz
+L{1}.r = [0   0	  0	];
+L{2}.r = [0.068   0.006   -0.016];
+L{3}.r = [0   -0.070  0.014 ];
+L{4}.r = [0   0	  -0.019];
+L{5}.r = [0   0	  0	];
+L{6}.r = [0   0	  .032	];
+
+%        Ixx     Iyy      Izz    Ixy     Iyz     Ixz
+L{1}.I = [0   0	  0.35    0	  0	  0];
+L{2}.I = [.13     .524    .539    0   0	  0];
+L{3}.I = [.066    .0125   .066    0   0	  0];
+L{4}.I = [1.8e-3  1.8e-3  1.3e-3  0   0	  0];
+L{5}.I = [.3e-3   .3e-3   .4e-3   0   0	  0];
+L{6}.I = [.15e-3  .15e-3  .04e-3  0   0	  0];
+
+L{1}.Jm =  200e-6;
+L{2}.Jm =  200e-6;
+L{3}.Jm =  200e-6;
+L{4}.Jm =  33e-6;
+L{5}.Jm =  33e-6;
+L{6}.Jm =  33e-6;
+
+%L{1}.G =  1.0;
+%L{2}.G =  1.0;
+%L{3}.G =  1.0;
+%L{4}.G =  1.0;
+%L{5}.G =  1.0;
+%L{6}.G =  1.0;
+
+L{1}.G =  -62.6111;
+L{2}.G =  107.815;
+L{3}.G =  -53.7063;
+L{4}.G =  76.0364;
+L{5}.G =  71.923;
+L{6}.G =  76.686;
+
+% viscous friction (motor referenced)
+L{1}.B =   1.48e-3;
+L{2}.B =   .817e-3;
+L{3}.B =    1.38e-3;
+L{4}.B =   71.2e-6;
+L{5}.B =   82.6e-6;
+L{6}.B =   36.7e-6;
+
+% Coulomb friction (motor referenced)
+L{1}.Tc = [ 0.0  0.0];
+L{2}.Tc = [ 0.0  0.0];
+L{3}.Tc = [ 0.0  0.0];
+L{4}.Tc = [ 0.0  0.0];
+L{5}.Tc = [ 0.0  0.0];
+L{6}.Tc = [ 0.0  0.0];
+
+%L{1}.Tc = [ .395	-.435];
+%L{2}.Tc = [ .126	-.071];
+%L{3}.Tc = [ .132	-.105];
+%L{4}.Tc = [ 11.2e-3 -16.9e-3];
+%L{5}.Tc = [ 9.26e-3 -14.5e-3];
+%L{6}.Tc = [ 3.96e-3 -10.5e-3];
+
+%
+% some useful poses
+%
+qz = [0 0 0 0 0 0]; % zero angles, L shaped pose
+qr = [0 -pi/2 pi/2 0 0 0]; % ready pose, arm up
+qstretch = [0 0 pi/2 0 0 0]; % horizontal along x-axis
+
+p560m = robot(L, 'Puma560-AKB', 'Unimation', 'AK&B');
+clear L
+
+
Index: Motion/roboop/extra/puma560akb_no_motor.m
===================================================================
RCS file: Motion/roboop/extra/puma560akb_no_motor.m
diff -N Motion/roboop/extra/puma560akb_no_motor.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/puma560akb_no_motor.m	14 Jul 2004 02:29:41 -0000	1.2
@@ -0,0 +1,122 @@
+%PUMA560AKB Load kinematic and dynamic data for a Puma 560 manipulator
+%
+%	PUMA560AKB
+%
+% Defines the object 'p560m' in current workspace which describes the 
+% kinematic and dynamic characterstics of a Unimation Puma 560 manipulator 
+% modified DH conventions and using the data and conventions of:
+%
+%	Armstrong, Khatib and Burdick 1986.
+%	"The Explicit Dynamic Model and Inertial Parameters of the Puma 560 Arm"
+%
+% Also define the vector qz which corresponds to the zero joint
+% angle configuration, qr which is the vertical 'READY' configuration,
+% and qstretch in which the arm is stretched out in the X direction.
+%
+% See also: ROBOT, PUMA560, STANFORD, TWOLINK.
+
+% Copyright (C) 1993-2002, by Peter I. Corke
+% CHANGES:
+% 12/01	convert to object format
+% $Log: puma560akb_no_motor.m,v $
+% Revision 1.2  2004/07/14 02:29:41  ejt
+% update to roboop version 1.20
+%
+% Revision 1.2  2004/07/06 02:16:36  gourdeau
+% doxy etc
+%
+% Revision 1.1  2004/05/12 13:34:37  elachance
+% Initial revision
+%
+% Revision 1.1  2003/02/06 04:31:36  gourdeau
+% 1er rev Etienne L.
+%
+% Revision 1.1  2002/12/13 04:50:14  elachance
+% Initial revision
+%
+% Revision 1.3  2002/04/01 11:47:15  pic
+% General cleanup of code: help comments, see also, copyright, remnant dh/dyn
+% references, clarification of functions.
+%
+% $Revision: 1.2 $
+
+clear L
+%            alpha   A     theta    D	sigma
+L{1} = link([0       0       0       0       0], 'mod');
+L{2} = link([-pi/2   0       0       0  0], 'mod');
+L{3} = link([0       0.4318  0      -0.15005 0], 'mod');
+L{4} = link([-pi/2   0.0203 0       -.4318   0], 'mod');
+L{5} = link([pi/2   0       0       0       0], 'mod');
+L{6} = link([-pi/2    0       0       0       0], 'mod');
+
+%L{1} = link([0       0       0       0       0], 'mod');
+%L{2} = link([-pi/2   0       0       0.2435  0], 'mod');
+%L{3} = link([0       0.4318  0       -0.0934 0], 'mod');
+%L{4} = link([pi/2    -0.0203 0       .4331   0], 'mod');
+%L{5} = link([-pi/2   0       0       0       0], 'mod');
+%L{6} = link([pi/2    0       0       0       0], 'mod');
+
+L{1}.m = 0;
+L{2}.m = 17.4;
+L{3}.m = 4.8;
+L{4}.m = 0.82;
+L{5}.m = 0.34;
+L{6}.m = .09;
+
+%         rx      ry      rz
+L{1}.r = [0   0	  0	];
+L{2}.r = [0.068   0.006   -0.016];
+L{3}.r = [0   -0.070  0.014 ];
+L{4}.r = [0   0	  -0.019];
+L{5}.r = [0   0	  0	];
+L{6}.r = [0   0	  .032	];
+
+%        Ixx     Iyy      Izz    Ixy     Iyz     Ixz
+L{1}.I = [0   0	  0.35    0	  0	  0];
+L{2}.I = [.13     .524    .539    0   0	  0];
+L{3}.I = [.066    .0125   .066    0   0	  0];
+L{4}.I = [1.8e-3  1.8e-3  1.3e-3  0   0	  0];
+L{5}.I = [.3e-3   .3e-3   .4e-3   0   0	  0];
+L{6}.I = [.15e-3  .15e-3  .04e-3  0   0	  0];
+
+L{1}.Jm =  0;
+L{2}.Jm =  0;
+L{3}.Jm =  0;
+L{4}.Jm =  0;
+L{5}.Jm =  0;
+L{6}.Jm =  0;
+
+L{1}.G =  0;
+L{2}.G =  0;
+L{3}.G =  0;
+L{4}.G =  0;
+L{5}.G =  0;
+L{6}.G =  0;
+
+% viscous friction (motor referenced)
+L{1}.B =   0;
+L{2}.B =   0;
+L{3}.B =   0;
+L{4}.B =   0;
+L{5}.B =   0;
+L{6}.B =   0;
+
+% Coulomb friction (motor referenced)
+L{1}.Tc = [ 0.0  0.0];
+L{2}.Tc = [ 0.0  0.0];
+L{3}.Tc = [ 0.0  0.0];
+L{4}.Tc = [ 0.0  0.0];
+L{5}.Tc = [ 0.0  0.0];
+L{6}.Tc = [ 0.0  0.0];
+
+%
+% some useful poses
+%
+qz = [0 0 0 0 0 0]; % zero angles, L shaped pose
+qr = [0 -pi/2 pi/2 0 0 0]; % ready pose, arm up
+qstretch = [0 0 pi/2 0 0 0]; % horizontal along x-axis
+
+p560m = robot(L, 'Puma560-AKB', 'Unimation', 'AK&B');
+clear L
+
+
Index: Motion/roboop/extra/rtest.cpp
===================================================================
RCS file: Motion/roboop/extra/rtest.cpp
diff -N Motion/roboop/extra/rtest.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/rtest.cpp	14 Jul 2004 02:29:41 -0000	1.4
@@ -0,0 +1,565 @@
+/*
+ROBOOP -- A robotics object oriented package in C++
+Copyright (C) 1996-2004  Richard Gourdeau  and Etienne Lachance
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Report problems and direct all questions to:
+
+Richard Gourdeau
+Professeur Agrege
+Departement de genie electrique
+Ecole Polytechnique de Montreal
+C.P. 6079, Succ. Centre-Ville
+Montreal, Quebec, H3C 3A7
+
+email: richard.gourdeau@polymtl.ca
+
+-------------------------------------------------------------------------------
+Revision_history:
+
+2004/07/01: Ethan Tira-Thompson
+    -Added support for newmat's use_namespace #define, using ROBOOP namespace
+-------------------------------------------------------------------------------
+*/
+
+static const char rcsid[] = "$Id: rtest.cpp,v 1.4 2004/07/14 02:29:41 ejt Exp $";
+
+#include "robot.h"
+#include "quaternion.h"
+#include "precisio.h"
+#include <fstream>
+
+#ifdef use_namespace
+using namespace ROBOOP;
+#endif
+
+Real PUMA560_data_DH[] =
+   {0.0, 0.0, 0.0, 0.0, M_PI/2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.35, 0.0, 0.0,
+    0.0, 0.0, 0.0, 0.4318, 0.0, 17.4, -0.3638, 0.006, 0.2275, 0.13, 0.0, 0.0, 0.524, 0.0, 0.539,
+    0.0, 0.0, 0.15005, 0.0203, -M_PI/2.0, 4.8, -0.0203, -0.0141, 0.07, 0.066, 0.0, 0.0, 0.086, 0.0, 0.0125,
+    0.0, 0.0, 0.4318, 0.0, M_PI/2.0, 0.82, 0.0, 0.019, 0.0, 0.0018, 0.0, 0.0, 0.0013, 0.0, 0.0018,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 0.34, 0.0, 0.0, 0.0, 0.0003, 0.0, 0.0, 0.0004, 0.0, 0.0003,
+    0.0, 0.0, 0.0, 0.0, 0.0, 0.09, 0.0, 0.0, 0.032, 0.00015, 0.0, 0.0, 0.00015, 0.0, 0.00004};
+Real PUMA560_data_mDH[] =
+   //joint_type, theta, d, a, alpha
+   {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.35,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2, 17.4, 0.068, 0.006, -0.016, 0.13, 0.0, 0.0, 0.524, 0.0, 0.539,
+    0.0, 0.0, -0.15005, 0.4318, 0.0, 4.8, 0.0, -0.070, 0.014, 0.066, 0.0, 0.0, 0.0125, 0.0, 0.066,
+    0.0, 0.0, -0.4318, 0.0203, -M_PI/2.0, 0.82, 0.0, 0.0, -0.019, 0.0018, 0.0, 0.0, 0.0018, 0.0, 0.0013,
+    0.0, 0.0, 0.0, 0.0, M_PI/2.0, 0.34, 0.0, 0.0, 0.0, 0.0003, 0.0, 0.0, 0.0003, 0.0, 0.0004,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2, 0.09, 0.0, 0.0, 0.032, 0.00015, 0.0, 0.0, 0.00015, 0.0, 0.00004};
+Real PUMA560_motor[] =
+   {200e-6, -62.6111, 1.48e-3, 0, // using + and - directions average
+    200e-6, 107.815, .817e-3, 0,
+    200e-6, -53.7063, 1.38e-3, 0,
+    33e-6,  76.0364, 71.2e-6, 0,
+    33e-6,  71.923,  82.6e-6, 0,
+    33e-6,  76.686,  36.7e-6, 0};
+
+Real STANFORD_data_DH[] =
+   {0.0, 0.0, 0.412, 0.0, -M_PI/2, 9.29, 0.0, 0.0175, -0.1105, 0.276, 0.0, 0, 0.255, 0.0, 0.071,
+    0.0, 0.0, 0.154, 0.0, M_PI/2.0, 5.01, 0.0, -1.054, 0.0, 0.108, 0.0, 0.0, 0.018, 0.0, 0.1,
+    1.0, -M_PI/2.0, 0.0, 0.0, 0.0, 4.25, 0.0, 0.0, -6.447, 2.51, 0.0, 0.0, 2.51, 0.0, 0.006,
+    0.0, 0.0, 0.0, 0.0, -M_PI/2.0, 1.08, 0.0, 0.092, -0.054, 0.002, 0.0, 0.0, 0.001, 0.0, 0.001,
+    0.0, 0.0, 0.0, 0.0,  M_PI/2.0, 0.63, 0.0, 0.0, 0.566, 0.003, 0.0, 0.0, 0.003, 0.0, 0.0004,
+    0.0, 0.0, 0.263, 0.0, 0.0, 0.51, 0.0, 0.0, 1.5540, 0.013, 0.0, 0.0, 0.013, 0.0, 0.0003};
+
+int main(void)
+{
+   int i;
+   std::ifstream infile;
+   infile.open("source/test.txt");
+   if(!infile) {
+      cerr << "Cannot open file:";
+      cerr << "source/test.txt\n";
+      exit (1);
+   }
+   Matrix Test(4,4), p1(3,1);
+   Real a, eps = FloatingPointPrecision::Epsilon(); /* floating point eps */
+
+   cout << "=====================================================\n";
+   cout << " ROBOOP -- A robotics object oriented package in C++ \n";;
+   cout << " TEST program \n";
+   cout << "=====================================================\n";
+   cout << "\n";
+   cout << "Machine epsilon = " << eps << endl;
+   eps *= 150.0;
+
+   cout << "Testing translation : ";
+   Real ott[] = {1.0,2.0,3.0};
+   p1 << ott;
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-trans(p1)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing rotx : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-rotx(M_PI/6)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing roty : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-roty(M_PI/6)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing rotz : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-rotz(M_PI/6)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing roll-pitch-yaw : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-rpy(p1)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing rotation around vector : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-rotk(M_PI/2,p1)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   // R(z) with angle=pi/4.
+   cout << "Testing quaternion to rotation matrix : ";
+   for(i = 1; i <= 3; i++) {
+      for(int j = 1; j <= 3; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   {
+      //     quaternion from angle + vector
+      ColumnVector v(3); v(1)=v(2)=0.0; v(3)=1.0;
+      Quaternion q(M_PI/4, v);
+      a = (Test.SubMatrix(1,3,1,3)-q.R()).MaximumAbsoluteValue();
+      if(a > eps) {
+         cout << "Erreur = " << a << endl;
+      } else {
+         cout << "Ok" << endl;
+      }
+   }
+
+   cout << "Testing quaternion to rotation matrix : ";
+   for(i = 1; i <= 3; i++) {
+      for(int j = 1; j <= 3; j++) {
+         infile >> Test(i,j);
+      }
+   }
+
+   {
+      // quaternion from 4 parameters
+      Quaternion q(M_PI/4, M_PI/6, M_PI/8, 1);
+      q.unit();
+      a = (Test.SubMatrix(1,3,1,3)-q.R()).MaximumAbsoluteValue();
+      if(a > eps) {
+         cout << "Erreur = " << a << endl;
+      } else {
+         cout << "Ok" << endl;
+      }
+
+      cout << "Testing quaternion to transformation matrix : ";
+      for(i = 1; i <= 4; i++) {
+         for(int j = 1; j <= 4; j++) {
+            infile >> Test(i,j);
+         }
+      }
+      a = (Test-q.T()).MaximumAbsoluteValue();
+      if(a > eps) {
+         cout << "Erreur = " << a << endl;
+      } else {
+         cout << "Ok" << endl;
+      }
+
+      cout << "Testing rotation matrix to quaternion : ";
+      ColumnVector quat(4);
+      Quaternion qq(q.R());
+      Test = Matrix(4,1);
+      for(i = 1; i <= 4; i++) {
+         infile >> Test(i,1);
+      }
+      quat(1) = qq.s();
+      quat.SubMatrix(2,4,1,1) = qq.v();
+      a = (Test-quat).MaximumAbsoluteValue();
+      if(a > eps) {
+         cout << "Erreur = " << a << endl;
+      } else {
+         cout << "Ok" << endl;
+      }
+
+      cout << "Testing transformation matrix to quaternion : ";
+      qq = Quaternion(q.T());
+      Test = Matrix(4,1);
+      for(i = 1; i <= 4; i++) {
+         infile >> Test(i,1);
+      }
+      quat(1) = qq.s();
+      quat.SubMatrix(2,4,1,1) = qq.v();
+      a = (Test-quat).MaximumAbsoluteValue();
+      if(a > eps) {
+         cout << "Erreur = " << a << endl;
+      } else {
+         cout << "Ok" << endl;
+      }
+   }
+
+
+   // ---------------------- R O B O T S -------------------------------------
+   Robot robot_DH;
+   mRobot robot_mDH;
+   Matrix initrob;
+
+   short dof;
+
+   ColumnVector qr, q, qd, qdd;
+   ColumnVector Fext(3), Next(3);
+
+   // Puma 560 in DH notation without motor
+   cout << "Testing Puma 560 (DH) forward kinematic : ";
+   Test = Matrix(4,4);
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   initrob = Matrix(6,15);
+   initrob << PUMA560_data_DH;
+   robot_DH = Robot(initrob);
+   dof = robot_DH.get_dof();
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot_DH.set_q(qr);
+   a = (Test-robot_DH.kine()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (DH) jacobian in base frame : ";
+   Test = Matrix(6,6);
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.jacobian()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (DH) jacobian in tool frame : ";
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.jacobian(dof)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   Test = Matrix(dof,1); Test = 0;
+   cout << "Testing Puma 560 (DH) torque : ";
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   qd = qr;
+   qdd = qr;
+   a = (Test-robot_DH.torque(qr, qd, qdd)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (DH) inertia : ";
+   Test = Matrix(6,6);
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++){
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.inertia(qr)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   Matrix initrobm = Matrix(6,4);
+   initrobm << PUMA560_motor;
+   robot_DH = Robot(initrob,initrobm);
+   dof = robot_DH.get_dof();
+
+   cout << "Testing Puma 560 (DH) motor, torque : ";
+   Test = Matrix(dof,1);
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_DH.torque(qr, qd, qdd)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   // Stanford in DH notation
+   cout << "Testing Stanford (DH) forward kinematic : ";
+   Test = Matrix(4,4);
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   initrob = Matrix(6,15);
+   initrob << STANFORD_data_DH;
+   robot_DH = Robot(initrob);
+   dof = robot_DH.get_dof();
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot_DH.set_q(qr);
+   a = (Test-robot_DH.kine()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Stanford (DH) jacobian in base frame : ";
+   Test = Matrix(6,6);
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.jacobian()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Stanford (DH) jacobian in tool frame : ";
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.jacobian(dof)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   Test = Matrix(dof,1); Test = 0;
+   cout << "Testing Stanford (DH) torque : ";
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_DH.torque(qr, qd, qdd)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Stanford (DH) torque with load on link n: ";
+   Fext(1)=10; Fext(2)=5; Fext(3)=7;
+   Next(1)=11; Next(2)=22; Next(3)=33;
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_DH.torque(qr, qd, qdd, Fext, Next)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Stanford (DH) inertia : ";
+   Test = Matrix(6,6); Test = 0;
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++){
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_DH.inertia(qr)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   Test = Matrix(4,4);
+
+   // ATTENTION J'AI CHANGE LES PARAMETRES DH DANS PUMA560AKD.M, j'ai ecris a P. Corke
+   // Puma 560 DH modified
+   cout << "Testing Puma 560 (mDH) forward kinematic : ";
+   for(i = 1; i <= 4; i++) {
+      for(int j = 1; j <= 4; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   initrob = Matrix(6,15);
+   initrob << PUMA560_data_mDH;
+   robot_mDH = mRobot(initrob);
+   dof = robot_mDH.get_dof();
+   qr = ColumnVector(dof);
+   qr = M_PI/4.0;
+   robot_mDH.set_q(qr);
+   a = (Test-robot_mDH.kine()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   // faut revoir jacobian pour dernier link
+   cout << "Testing Puma 560 (mDH) jacobian in base frame : ";
+   Test = Matrix(6,6);
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_mDH.jacobian()).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (mDH) jacobian in tool frame : ";
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++) {
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_mDH.jacobian(dof)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (mDH) torque : ";
+   Test = Matrix(dof,1);
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_mDH.torque(qr, qd, qdd)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (mDH) inertia : ";
+   Test = Matrix(6,6); Test = 0;
+   for(i = 1; i <= 6; i++) {
+      for(int j = 1; j <= 6; j++){
+         infile >> Test(i,j);
+      }
+   }
+   a = (Test-robot_mDH.inertia(qr)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (mDH) motor, torque : ";
+   initrobm = Matrix(6,4);
+   initrobm << PUMA560_motor;
+   robot_mDH = mRobot(initrob,initrobm);
+   dof = robot_mDH.get_dof();
+   Test = Matrix(dof,1);
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_mDH.torque(qr, qd, qdd)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   cout << "Testing Puma 560 (mDH) motor, torque with load on link n: ";
+   Fext(1)=10; Fext(2)=5; Fext(3)=7;
+   Next(1)=11; Next(2)=22; Next(3)=33;
+   for(i = 1; i <= dof; i++) {
+      infile >> Test(i,1);
+   }
+   a = (Test-robot_mDH.torque(qr, qd, qdd, Fext, Next)).MaximumAbsoluteValue();
+   if(a > eps) {
+      cout << "Erreur = " << a << endl;
+   } else {
+      cout << "Ok" << endl;
+   }
+
+   return(0);
+}
Index: Motion/roboop/extra/stanford_no_motor.m
===================================================================
RCS file: Motion/roboop/extra/stanford_no_motor.m
diff -N Motion/roboop/extra/stanford_no_motor.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/stanford_no_motor.m	14 Jul 2004 02:29:41 -0000	1.2
@@ -0,0 +1,56 @@
+%STANFORD Load kinematic and dynamic data for Stanford arm
+%
+% Defines the object 'stanford' in the current workspace which describes the 
+% kinematic and dynamic characterstics of the Stanford (Scheinman) arm.
+%
+% Kinematic data from "Modelling, Trajectory calculation and Servoing of 
+% a computer controlled arm".  Stanford AIM-177.  Figure 2.3
+% Dynamic data from "Robot manipulators: mathematics, programming and control"
+% Paul 1981, Tables 6.4, 6.6
+% 
+% Note: gear ratios not currently known, though reflected armature inertia 
+% is known, so gear ratios set to 1.
+%
+% Also define the vector qz which corresponds to the zero joint
+% angle configuration.
+%
+% See also: ROBOT, PUMA560, PUMA560AKB, TWOLINK.
+
+% $Log: stanford_no_motor.m,v $
+% Revision 1.2  2004/07/14 02:29:41  ejt
+% update to roboop version 1.20
+%
+% Revision 1.2  2004/07/06 02:16:37  gourdeau
+% doxy etc
+%
+% Revision 1.1  2004/05/12 13:34:37  elachance
+% Initial revision
+%
+% Revision 1.1  2003/02/06 04:18:59  gourdeau
+% no message
+%
+% Revision 1.1  2002/12/13 04:50:22  elachance
+% Initial revision
+%
+% Revision 1.2  2002/04/01 11:47:18  pic
+% General cleanup of code: help comments, see also, copyright, remnant dh/dyn
+% references, clarification of functions.
+%
+% $Revision: 1.2 $
+% Copyright (C) 1990-2002, by Peter I. Corke
+
+% alpha A	theta	D	sigma	m	rx	ry	rz	Ixx	Iyy	Izz	Ixy	Iyz	Ixz	Jm	G
+stanford_dyn = [
+-pi/2 0	0	0.412	0	9.29	0	.0175	-0.1105	0.276	0.255	0.071	0	0	0	0	1
+pi/2 0	0	0.154	0	5.01	0	-1.054	0	0.108	0.018	0.100	0	0	0	0	1	
+0 0	-pi/2	0	1	4.25	0	0	-6.447	2.51	2.51	0.006	0	0	0	0	1
+-pi/2 0	0	0	0	1.08	0	0.092	-0.054	0.002	0.001	0.001	0	0	0	0	1
+pi/2 0	0	0	0	0.63	0	0	0.566	0.003	0.003	0.0004	0	0	0	0	1
+0 0	0	0.263	0	0.51	0	0	1.554	0.013	0.013	0.0003	0	0	0	0	1
+];
+
+qz = [0 0 0 0 0 0];
+
+stanf = robot(stanford_dyn);
+stanf.plotopt = {'workspace', [-2 2 -2 2 -2 2]};
+stanf.name = 'Stanford arm';
Index: Motion/roboop/extra/test.txt
===================================================================
RCS file: Motion/roboop/extra/test.txt
diff -N Motion/roboop/extra/test.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/test.txt	16 Jun 2004 21:50:00 -0000	1.1
@@ -0,0 +1,109 @@
+   1.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   0.0000000000000000e+00   1.0000000000000000e+00   0.0000000000000000e+00   2.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00   3.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   1.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   0.0000000000000000e+00   8.6602540378443871e-01  -4.9999999999999994e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   4.9999999999999994e-01   8.6602540378443871e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   8.6602540378443871e-01   0.0000000000000000e+00   4.9999999999999994e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   1.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -4.9999999999999994e-01   0.0000000000000000e+00   8.6602540378443871e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   8.6602540378443871e-01  -4.9999999999999994e-01   0.0000000000000000e+00   0.0000000000000000e+00
+   4.9999999999999994e-01   8.6602540378443871e-01   0.0000000000000000e+00   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   4.1198224566568298e-01  -8.3373765177415671e-01  -3.6763046292489920e-01   0.0000000000000000e+00
+  -5.8726644927620981e-02  -4.2691762127620736e-01   9.0238158548333081e-01   0.0000000000000000e+00
+  -9.0929742682568171e-01  -3.5017548837401463e-01  -2.2484509536615291e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   7.1428571428571480e-02  -6.5892658288013028e-01   7.4880819811056309e-01   0.0000000000000000e+00
+   9.4464086859441609e-01   2.8571428571428575e-01   1.6131018665900415e-01   0.0000000000000000e+00
+  -3.2023676953913449e-01   6.9583267048385289e-01   6.4285714285714290e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   7.0710678118654746e-01  -7.0710678118654757e-01   0.0000000000000000e+00
+   7.0710678118654757e-01   7.0710678118654746e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+  -1.2869363987542859e-01  -5.6696279532577232e-01   8.1362837694613410e-01
+   9.6910419230634393e-01  -2.4598488066142865e-01  -1.8124650072542547e-02
+   2.1041628147527658e-01   7.8615814388860072e-01   5.8110271147857129e-01
+  -1.2869363987542859e-01  -5.6696279532577232e-01   8.1362837694613410e-01   0.0000000000000000e+00
+   9.6910419230634393e-01  -2.4598488066142865e-01  -1.8124650072542547e-02   0.0000000000000000e+00
+   2.1041628147527658e-01   7.8615814388860072e-01   5.8110271147857129e-01   0.0000000000000000e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   5.4918671482058679e-01   3.6612447654705793e-01   2.7459335741029350e-01   6.9924624275276381e-01
+   5.4918671482058679e-01   3.6612447654705793e-01   2.7459335741029350e-01   6.9924624275276381e-01
+  -9.5710678118654746e-01   2.4999999999999983e-01  -1.4644660940672630e-01   1.6672664400690266e-02
+   2.5000000000000006e-01   4.5710678118654735e-01  -8.5355339059327384e-01  -1.9553008063339261e-01
+  -1.4644660940672605e-01  -8.5355339059327384e-01  -4.9999999999999989e-01   3.2562870811635125e-01
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+   1.9553008063339264e-01  -2.3025426765808690e-01  -1.4354267658086927e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   1.6672664400690228e-02  -2.3025426765808688e-01  -1.4354267658086936e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -6.6763136902583953e-18  -1.2647129188364875e-01  -4.3180000000000002e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   7.2438257649187765e-18   7.0710678118654746e-01   7.0710678118654746e-01  -7.0710678118654735e-01   5.0000000000000000e-01  -1.4644660940672630e-01
+  -1.9109063290057016e-17  -7.0710678118654768e-01  -7.0710678118654768e-01  -7.0710678118654746e-01  -5.0000000000000000e-01  -8.5355339059327384e-01
+   9.9999999999999989e-01  -2.3581397251559721e-18  -2.3581397251559721e-18   1.5027042110649091e-16   7.0710678118654746e-01  -4.9999999999999989e-01
+  -1.8297499999999997e-01   1.8133564594182439e-01   7.3385645941824354e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   5.6503708116351185e-02  -5.4864354058175552e-02   3.5841435405817568e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -4.2865726575217089e-02   2.9348991359991128e-01   2.3025426765808688e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -1.4644660940672613e-01  -8.5355339059327373e-01  -8.5355339059327373e-01   4.9999999999999994e-01  -7.0710678118654746e-01   0.0000000000000000e+00
+  -8.5355339059327384e-01  -1.4644660940672635e-01  -1.4644660940672635e-01  -4.9999999999999994e-01  -7.0710678118654757e-01   0.0000000000000000e+00
+  -4.9999999999999978e-01   5.0000000000000000e-01   5.0000000000000000e-01   7.0710678118654757e-01   6.1232339957367660e-17   1.0000000000000000e+00
+   6.7796663502212995e-01   1.7558551669236614e+01  -8.2406093183092359e+00   1.3497917891563878e-02  -9.6275614517582660e-03   6.6344845002793933e-05
+   2.1278239286730556e+00  -5.0893470591099033e-01  -3.5201387500000338e-03   2.5359301375479058e-04   9.4176630376828691e-04  -1.9999999999999998e-05
+  -5.0893470591099010e-01   1.5780811483055852e+00   9.5429533082167742e-02  -2.5359301375479064e-04  -2.6937939936082614e-05   1.9999999999999998e-05
+  -3.5201387499999904e-03   9.5429533082167825e-02   3.6089191985875024e-01  -6.9326635344233931e-04   1.0345273997514632e-03   1.9999999999999998e-05
+   2.5359301375479096e-04  -2.5359301375479031e-04  -6.9326635344233573e-04   1.7410799999999999e-03   1.6170977975373631e-20   2.8284271247461906e-05
+   9.4176630376828681e-04  -2.6937939936082881e-05   1.0345273997514630e-03   2.6345717853171403e-20   6.4216000000000002e-04   2.4492935982947065e-21
+  -1.9999999999999998e-05   2.0000000000000002e-05   2.0000000000000002e-05   2.8284271247461906e-05   2.4492935982947065e-21   4.0000000000000003e-05
+   1.2209638608786406e+00   1.9453638662078866e+01  -7.8457436074405278e+00   1.6759650728503975e-01   1.2911077116399716e-01   1.5469465707587318e-01
+   7.3223304703363218e-02  -2.8033008588991065e-01   9.5710678118654746e-01   5.3552372084805777e-01
+   2.8033008588991065e-01   9.2677669529663687e-01   2.4999999999999994e-01   5.6734352600145244e-01
+  -9.5710678118654746e-01   2.4999999999999997e-01   1.4644660940672635e-01   1.0058758255437648e+00
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+  -5.6734352600145233e-01   4.1993362342475515e-01   4.9999999999999994e-01  -2.7234541726031004e-02   6.5750000000000017e-02   0.0000000000000000e+00
+   5.3552372084805777e-01   4.1993362342475515e-01   4.9999999999999994e-01   1.5873454172603099e-01  -1.2021908345206198e-01   0.0000000000000000e+00
+  -4.1118367391512756e-17  -7.7984490899582659e-01   7.0710678118654746e-01  -9.2984541726030975e-02  -2.2448454172603097e-01   0.0000000000000000e+00
+  -1.8282359133536819e-17  -7.0710678118654735e-01   0.0000000000000000e+00   4.9999999999999994e-01  -1.4644660940672613e-01   9.5710678118654746e-01
+   1.9112451421846033e-17   7.0710678118654757e-01   0.0000000000000000e+00   4.9999999999999994e-01   8.5355339059327384e-01   2.4999999999999994e-01
+   9.9999999999999989e-01  -1.3694828691207528e-17   0.0000000000000000e+00   7.0710678118654746e-01  -4.9999999999999989e-01   1.4644660940672635e-01
+   1.0858064278553578e-01   8.9486380705965296e-01  -4.9999999999999994e-01   1.3149999999999998e-01   1.8596908345206198e-01   0.0000000000000000e+00
+   6.5535436363359356e-01   7.6503439789857325e-02   4.9999999999999994e-01   1.3150000000000001e-01  -1.8596908345206198e-01   0.0000000000000000e+00
+  -4.0912740578626200e-01   3.9269908169872414e-01   7.0710678118654757e-01  -1.3877787807814457e-17   0.0000000000000000e+00   0.0000000000000000e+00
+  -9.5710678118654746e-01   1.4644660940672619e-01   0.0000000000000000e+00  -4.9999999999999994e-01   7.0710678118654746e-01   0.0000000000000000e+00
+   2.5000000000000000e-01   8.5355339059327373e-01   0.0000000000000000e+00   4.9999999999999994e-01   7.0710678118654757e-01   0.0000000000000000e+00
+   1.4644660940672632e-01  -4.9999999999999989e-01   0.0000000000000000e+00   7.0710678118654757e-01   6.1232339957367660e-17   1.0000000000000000e+00
+   1.3745229727442040e+02   1.9073728601445512e+02   6.6163665806434153e+01   3.0629709003685834e-02  -9.1835952755811263e+00  -1.9326583776879398e-04
+   1.3875554719730982e+02   2.0670642215241801e+02   6.8613413274739997e+01   3.0837653488159756e+01   1.5080773920835252e+01   3.2999806734162235e+01
+   7.7509509360976978e+01   2.9249274096357913e+00  -2.2168966615983357e-01   1.4124673103028331e+00  -1.2781840784752210e+00   4.3933982822017903e-05
+   2.9249274096357922e+00   1.4283361944665964e+02  -6.0038653252120033e-01   1.2045896408528984e+00   1.8485538046404897e+00  -1.4999999999999996e-04
+  -2.2168966615983374e-01  -6.0038653252120067e-01   6.4700000000000006e+00  -3.0879524070565371e-17  -9.0739477695763715e-01   0.0000000000000000e+00
+   1.4124673103028331e+00   1.2045896408528984e+00   3.0879524070565371e-17   9.5529111500000008e-01  -5.9125778775587401e-17   2.1213203435596425e-04
+  -1.2781840784752205e+00   1.8485538046404897e+00  -9.0739477695763704e-01   5.1000559010553399e-17   1.9015836700000002e+00   1.8369701987210296e-20
+   4.3933982822017910e-05  -1.4999999999999999e-04   0.0000000000000000e+00   2.1213203435596425e-04   1.8369701987210296e-20   2.9999999999999997e-04
+   2.5000000000000000e-01   4.5710678118654741e-01  -8.5355339059327362e-01   6.2733008063339268e-01
+  -9.5710678118654768e-01   2.4999999999999975e-01  -1.4644660940672630e-01   4.1512733559930975e-01
+   1.4644660940672607e-01   8.5355339059327384e-01   4.9999999999999983e-01  -3.2562870811635114e-01
+   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00   1.0000000000000000e+00
+  -4.1512733559930981e-01  -2.3025426765808685e-01  -1.4354267658086886e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   6.2733008063339279e-01  -2.3025426765808682e-01  -1.4354267658086837e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -1.0217250222960272e-16  -7.3712870811635123e-01  -4.3179999999999996e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   3.9925745001778701e-17  -7.0710678118654746e-01  -7.0710678118654746e-01  -7.0710678118654735e-01  -5.0000000000000000e-01  -8.5355339059327362e-01
+   5.7259427234390703e-18   7.0710678118654757e-01   7.0710678118654757e-01  -7.0710678118654746e-01   5.0000000000000022e-01  -1.4644660940672630e-01
+   9.9999999999999989e-01  -1.0053264644371840e-16  -1.0053264644371840e-16  -1.6750923564901044e-16  -7.0710678118654746e-01   4.9999999999999983e-01
+  -7.0420370811635125e-01   5.4864354058175718e-02  -5.3085645941824348e-02   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+  -3.2925000000000176e-02  -7.9199306217452681e-01  -3.7871435405817561e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   2.6246298154113412e-01  -1.3831008640008863e-01  -2.0154573234191309e-01   0.0000000000000000e+00   0.0000000000000000e+00   0.0000000000000000e+00
+   1.4644660940672599e-01  -8.5355339059327373e-01  -8.5355339059327373e-01   5.0000000000000000e-01  -7.0710678118654746e-01   0.0000000000000000e+00
+   8.5355339059327384e-01  -1.4644660940672638e-01  -1.4644660940672638e-01  -4.9999999999999994e-01  -7.0710678118654757e-01   0.0000000000000000e+00
+   4.9999999999999989e-01   4.9999999999999994e-01   4.9999999999999994e-01   7.0710678118654757e-01   6.1232339957367660e-17   1.0000000000000000e+00
+  -2.7573985771749243e-01  -3.0817730465264226e+01  -8.1275815489521701e+00  -8.3048256408445181e-03   9.9269467866774444e-03   1.6754941353508068e-04
+   2.2754414775769449e+00  -2.7445068783798021e-01  -3.6627547499999791e-03   9.8999098624520925e-04   9.1296160192987151e-04   1.9999999999999995e-05
+  -2.7445068783798016e-01   2.6431583112094739e+00   6.1620942117536204e-01   9.8999098624520925e-04  -1.2705219399360829e-03   2.0000000000000002e-05
+  -3.6627547499999374e-03   6.1620942117536215e-01   3.3737453314124988e-01   5.5031764655766389e-04  -2.0905660024853713e-04   2.0000000000000002e-05
+   9.8999098624520925e-04   9.8999098624520947e-04   5.5031764655766378e-04   1.7410799999999999e-03   2.0500758256551102e-20   2.8284271247461906e-05
+   9.1296160192987173e-04  -1.2705219399360827e-03  -2.0905660024853696e-04   3.0675498134348874e-20   6.4216000000000002e-04   2.4492935982947065e-21
+   1.9999999999999998e-05   2.0000000000000002e-05   2.0000000000000002e-05   2.8284271247461906e-05   2.4492935982947065e-21   4.0000000000000003e-05
+   2.6725736813901835e-01  -2.8922643472421974e+01  -7.7327158380834620e+00   1.4579376375263137e-01   1.4866527940243285e-01   1.5479586164440548e-01
+   3.1786923454289454e+01  -2.9413048550987469e+01  -7.6788768976599711e+00   1.7980317542908701e+01  -2.3185858499753635e+01   3.3154795861644402e+01
Index: Motion/roboop/extra/conf/pd_2dof.conf
===================================================================
RCS file: Motion/roboop/extra/conf/pd_2dof.conf
diff -N Motion/roboop/extra/conf/pd_2dof.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/pd_2dof.conf	14 Jul 2004 02:29:48 -0000	1.1
@@ -0,0 +1,12 @@
+[CONTROLLER]
+
+type:   PROPORTIONAL_DERIVATIVE
+dof:    2
+
+[GAINS]
+
+Kp_1:   25.0
+Kp_2:   25.0
+Kd_1:    7.0
+Kd_2:    7.0
+ 
Index: Motion/roboop/extra/conf/puma560_dh.conf
===================================================================
RCS file: Motion/roboop/extra/conf/puma560_dh.conf
diff -N Motion/roboop/extra/conf/puma560_dh.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/puma560_dh.conf	14 Jul 2004 02:29:48 -0000	1.2
@@ -0,0 +1,169 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+[Default]
+
+[PUMA560_DH]
+
+DH:           1
+Fix:          0
+MinPara:      0
+dof:          6
+Motor:        0
+
+[PUMA560_DH_LINK1]
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.35
+Iyz:          0.0
+Izz:          0.0
+Im:         200e-6
+Gr:          62.6111
+B:            1.48e-3
+Cf:           0.415
+
+[PUMA560_DH_LINK2]
+joint_type:   0
+theta:        0.0 
+d:            0.0
+a:            0.4318
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:           17.4
+cx:          -0.3638
+cy:           0.006
+cz:           0.2275
+Ixx:          0.13
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.524
+Iyz:          0.0
+Izz:          0.539
+Im:         200e-6
+Gr:         107.815  
+B:            0.817e-3
+Cf:           0.0985
+
+[PUMA560_DH_LINK3]
+joint_type:   0
+theta:        0.0
+d:            0.15005
+a:            0.0203
+alpha:       -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            4.8
+cx:          -0.0203
+cy:          -0.0141
+cz:           0.07
+Ixx:          0.066
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.086
+Iyz:          0.0
+Izz:          0.0125
+Im:           200e-6
+Gr:           53.7063
+B:            1.38e-3
+Cf:           0.1185
+
+[PUMA560_DH_LINK4]
+joint_type:  0
+theta:        0.0
+d:            0.4318
+a:            0.0
+alpha:        1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.82
+cx:           0.0
+cy:           0.019
+cz:           0.0
+Ixx:          0.0018
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0013
+Iyz:          0.0
+Izz:          0.0018
+Im:          33e-6
+Gr:          76.0364 
+B:           71.2e-6
+Cf:           0.01405
+
+[PUMA560_DH_LINK5]
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:       -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.34
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0003
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0004
+Iyz:          0.0
+Izz:          0.0003
+Im:          33e-6
+Gr:          71.923
+B:           82.6e-6
+Cf:           0.01188
+
+[PUMA560_DH_LINK6]
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.09
+cx:           0.0
+cy:           0.0
+cz:           0.032
+Ixx:          0.00015
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.00015
+Iyz:          0.0
+Izz:          0.00004
+Im:          33e-6
+Gr:          76.686
+B:           36.7e-6
+Cf:           0.00723
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/extra/conf/puma560_mdh.conf
===================================================================
RCS file: Motion/roboop/extra/conf/puma560_mdh.conf
diff -N Motion/roboop/extra/conf/puma560_mdh.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/puma560_mdh.conf	14 Jul 2004 02:29:48 -0000	1.2
@@ -0,0 +1,200 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+[PUMA560_mDH]
+
+DH:           0
+Fix:          1
+MinPara:      0
+dof:          6
+Motor:        1
+
+[PUMA560_mDH_LINK1]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.35
+Im:         200e-6
+Gr:          62.6111
+B:            1.48e-3
+Cf:           0.415
+
+[PUMA560_mDH_LINK2]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:       -1.57079632679489656
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:           17.4
+cx:           0.068
+cy:           0.006
+cz:          -0.016
+Ixx:          0.13
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.524
+Iyz:          0.0
+Izz:          0.539
+Im:         200e-6
+Gr:         107.815  
+B:            0.817e-3
+Cf:           0.0985
+
+[PUMA560_mDH_LINK3]
+
+joint_type:   0
+theta:        0.0
+d:           -0.15005
+a:            0.4318
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_type:   0
+m:            4.8
+cx:           0.0
+cy:          -0.07
+cz:           0.014
+Ixx:          0.066
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0125
+Iyz:          0.0
+Izz:          0.066
+Im:           200e-6
+Gr:           53.7063
+B:            1.38e-3
+Cf:           0.1185
+
+[PUMA560_mDH_LINK4]
+
+joint_type:   0
+theta:        0.0
+d:            0.4318
+a:            0.0203
+alpha:       -1.57079632679489656
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.82
+cx:           0.0
+cy:           0.0
+cz:          -0.019
+Ixx:          0.0018
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0018
+Iyz:          0.0
+Izz:          0.0013
+Im:          33e-6
+Gr:          76.0364 
+B:           71.2e-6
+Cf:           0.01405
+
+[PUMA560_mDH_LINK5]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        1.57079632679489656
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.34
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0003
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0003
+Iyz:          0.0
+Izz:          0.0004
+Im:          33e-6
+Gr:          71.923
+B:           82.6e-6
+Cf:           0.01188
+
+[PUMA560_mDH_LINK6]
+
+joint_type:   0
+theta:        0.0
+d:            0.3
+a:            0.0
+alpha:       -1.57079632679489656
+theta_min:    0.0
+theta_max:    0.0
+joint_offset:   0.0
+m:            0.09
+cx:           0.0
+cy:           0.0
+cz:           0.032
+Ixx:          0.00015
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.00015
+Iyz:          0.0
+Izz:          0.00004
+Im:          33e-6
+Gr:          76.686
+B:           36.7e-6
+Cf:           0.00723
+
+[PUMA560_mDH_LINK7]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/extra/conf/rhino_dh.conf
===================================================================
RCS file: Motion/roboop/extra/conf/rhino_dh.conf
diff -N Motion/roboop/extra/conf/rhino_dh.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/rhino_dh.conf	14 Jul 2004 02:29:48 -0000	1.2
@@ -0,0 +1,151 @@
+# ----------------------------------------------------------------
+# Rhino DH notation configuration File
+# ----------------------------------------------------------------
+
+[rhino_dh]
+
+Name:         Rhino
+DH:           1
+Fix:          0
+MinPara:      0
+dof:          5
+Motor:        0
+Stl:          0
+
+[rhino_dh_LINK1]
+
+joint_type:   0
+theta:        0.0
+d:            0.2604
+a:            0.0
+alpha:       -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rhino_dh_LINK2]
+
+joint_type:   0
+theta:        0.0 
+d:            0.0
+a:            0.2286
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0  
+B:            0.0
+Cf:           0.0
+
+[rhino_dh_LINK3]
+
+joint_type:  0
+theta:        0.0
+d:            0.0
+a:            0.2286
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rhino_dh_LINK4]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.0095
+alpha:        -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0 
+B:            0.0
+Cf:           0.0
+
+[rhino_dh_LINK5]
+
+joint_type:   0
+theta:        0.0
+d:            0.135
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/extra/conf/rhino_mdh.conf
===================================================================
RCS file: Motion/roboop/extra/conf/rhino_mdh.conf
diff -N Motion/roboop/extra/conf/rhino_mdh.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/rhino_mdh.conf	14 Jul 2004 02:29:48 -0000	1.2
@@ -0,0 +1,174 @@
+# ----------------------------------------------------------------
+# Rhino mDH notattion configuration File
+# ----------------------------------------------------------------
+
+[rhino_mdh]
+
+Name:         Rhino
+DH:           0
+Fix:          1
+MinPara:      0
+dof:          5
+Motor:        0
+Stl:          0
+
+[rhino_mdh_LINK1]
+joint_type:   0
+theta:        0.0
+d:            0.2604
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rhino_mdh_LINK2]
+
+joint_type:   0
+theta:        0.0 
+d:            0.0
+a:            0.0
+alpha:        -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0  
+B:            0.0
+Cf:           0.0
+
+[rhino_mdh_LINK3]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.2286
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rhino_mdh_LINK4]
+
+joint_type:   0
+theta:        0.0
+d:            0.0
+a:            0.2286
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0 
+B:            0.0
+Cf:           0.0
+
+[rhino_mdh_LINK5]
+
+joint_type:   0
+theta:        0.0
+d:            0.135
+a:            0.0095
+alpha:       -1.570796326794895
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rhino_mdh_LINK6]
+
+joint_type:   2
+theta:        0.0
+d:            0.0
+a:            0.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            0.0
+cx:           0.0
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0
+Iyz:          0.0
+Izz:          0.0
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+
+
+
+
+
+
+
+
+
+
+
Index: Motion/roboop/extra/conf/rr_dh.conf
===================================================================
RCS file: Motion/roboop/extra/conf/rr_dh.conf
diff -N Motion/roboop/extra/conf/rr_dh.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Motion/roboop/extra/conf/rr_dh.conf	14 Jul 2004 02:29:48 -0000	1.1
@@ -0,0 +1,70 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+
+[rr_dh]
+
+Name:         rr
+DH:           1
+Fix:          0
+dof:          2
+Motor:        0
+
+[rr_dh_LINK1]
+joint_type:   0
+theta:        0.1
+d:            0.0
+a:            1.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            2.0
+cx:          -0.5
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.1666666
+Iyz:          0.0
+Izz:          0.1666666
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+[rr_dh_LINK2]
+joint_type:   0
+theta:        0.5 
+d:            0.0
+a:            1.0
+alpha:        0.0
+theta_min:    0.0
+theta_max:    0.0
+joint_offset: 0.0
+m:            1.0
+cx:          -0.5
+cy:           0.0
+cz:           0.0
+Ixx:          0.0
+Ixy:          0.0
+Ixz:          0.0
+Iyy:          0.0833333
+Iyz:          0.0
+Izz:          0.0833333
+Im:           0.0
+Gr:           0.0
+B:            0.0
+Cf:           0.0
+
+
+
+
+
+
+
+
+
+
Index: Shared/Config.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/Config.cc,v
retrieving revision 1.30
retrieving revision 1.36
diff -u -d -r1.30 -r1.36
--- Shared/Config.cc	21 Jan 2004 03:53:01 -0000	1.30
+++ Shared/Config.cc	11 Oct 2004 22:01:34 -0000	1.36
@@ -4,8 +4,16 @@
 #include <stdio.h>
 #include <string>
 #include <ctype.h>
-#include <OPENR/OPrimitiveControl.h>
-#include <OPENR/OPENRAPI.h>
+#ifdef PLATFORM_APERIOS
+#  include <OPENR/OPrimitiveControl.h>
+#  include <OPENR/OPENRAPI.h>
+#else
+  typedef unsigned int OSpeakerVolume;
+  const OSpeakerVolume ospkvolinfdB = 0x8000;
+  const OSpeakerVolume ospkvol25dB  = 0xe700;
+  const OSpeakerVolume ospkvol18dB  = 0xee00;
+  const OSpeakerVolume ospkvol10dB  = 0xf600;
+#endif
 
 Config* config=NULL;
 
@@ -27,6 +35,7 @@
         } else if (strncasecmp(value,"outdoor",49)==0) {
           vision.white_balance=2;
         }
+#ifdef PLATFORM_APERIOS
 				//this will actually send the new setting to the system
 				OPrimitiveID fbkID = 0;
 				if(OPENR::OpenPrimitive(CameraLocator, &fbkID) != oSUCCESS){
@@ -38,6 +47,7 @@
 					}
 					OPENR::ClosePrimitive(fbkID);
 				}
+#endif
         return &vision.white_balance;
       } else if (strncasecmp(key,"gain",29)==0) {
         if (strncasecmp(value,"low",49)==0) {
@@ -47,6 +57,7 @@
         } else if (strncasecmp(value,"high",49)==0) {
           vision.gain=3;
         }
+#ifdef PLATFORM_APERIOS
 				//this will actually send the new setting to the system
 				OPrimitiveID fbkID = 0;
 				if(OPENR::OpenPrimitive(CameraLocator, &fbkID) != oSUCCESS){
@@ -57,6 +68,7 @@
 						std::cout << "CAM_SET_GAIN : Failed!" << std::endl;
 					OPENR::ClosePrimitive(fbkID);
 				}
+#endif
         return &vision.gain;
       } else if (strncasecmp(key,"shutter_speed",29)==0) {
         if (strncasecmp(value,"slow",49)==0) {
@@ -66,6 +78,7 @@
         } else if (strncasecmp(value,"fast",49)==0) {
           vision.shutter_speed=3;
         }
+#ifdef PLATFORM_APERIOS
 				//this will actually send the new setting to the system
 				OPrimitiveID fbkID = 0;
 				if(OPENR::OpenPrimitive(CameraLocator, &fbkID) != oSUCCESS){
@@ -76,6 +89,7 @@
 						std::cout << "CAM_SET_SHUTTER_SPEED : Failed!" << std::endl;
 					OPENR::ClosePrimitive(fbkID);
 				}
+#endif
         return &vision.shutter_speed;
       } else if (strncasecmp(key,"resolution",29)==0) {
         if (strncasecmp(value,"full",49)==0) {
@@ -86,6 +100,15 @@
           vision.resolution=3;
         }
         return &vision.resolution;
+      } else if (strncasecmp(key,"horizFOV",29)==0) {
+				vision.horizFOV=atof(value)*M_PI/180;
+        return &vision.horizFOV;
+      } else if (strncasecmp(key,"vertFOV",29)==0) {
+				vision.vertFOV=atof(value)*M_PI/180;
+        return &vision.vertFOV;
+      } else if (strncasecmp(key,"focal_length",29)==0) {
+				vision.focal_length=atof(value);
+        return &vision.focal_length;
       } else if (strncasecmp(key,"thresh",29)==0) {
 				vision.thresh.push_back(value);
         return &vision.thresh;
@@ -95,9 +118,21 @@
       } else if (strncasecmp(key,"raw_port",29)==0) {
         vision.rawcam_port=atoi(value);
         return &vision.rawcam_port;
+      } else if (strncasecmp(key,"raw_transport",29)==0) {
+        if (strncasecmp(value,"udp",49)==0)
+          vision.rawcam_transport=0;
+        else if (strncasecmp(value,"tcp",49)==0)
+          vision.rawcam_transport=1;
+        return &vision.rawcam_transport;
       } else if (strncasecmp(key,"rle_port",29)==0) {
         vision.rle_port=atoi(value);
         return &vision.rle_port;
+      } else if (strncasecmp(key,"rle_transport",29)==0) {
+        if (strncasecmp(value,"udp",49)==0)
+          vision.rle_transport=0;
+        else if (strncasecmp(value,"tcp",49)==0)
+          vision.rle_transport=1;
+        return &vision.rle_transport;
       } else if (strncasecmp(key,"obj_port",29)==0) {
         vision.obj_port=atoi(value);
         return &vision.obj_port;
@@ -111,8 +146,8 @@
           vision.jpeg_dct_method=JDCT_IFAST;
         } else if (strncasecmp(value,"float",49)==0) {
           vision.jpeg_dct_method=JDCT_FLOAT;
-				}
-				return &vision.jpeg_dct_method;
+		}
+		return &vision.jpeg_dct_method;
       } else if (strncasecmp(key,"rawcam_encoding",29)==0) {
         if (strncasecmp(value,"color",49)==0) {
           vision.rawcam_encoding=vision_config::ENCODE_COLOR;
@@ -246,6 +281,12 @@
 			} else if (strncasecmp(key,"walk",29)==0) {
         motion.walk=value;
         return &motion.walk;
+			} else if (strncasecmp(key,"kinematics",29)==0) {
+        motion.kinematics=value;
+        return &motion.walk;
+      } else if (strncasecmp(key,"kinematic_chains",29)==0) {
+				motion.kinematic_chains.push_back(value);
+        return &motion.kinematic_chains;
       } else if (strncasecmp(key,"estop_on_snd",29)==0) {
         strncpy(motion.estop_on_snd,value,49);
         return &motion.estop_on_snd;
@@ -253,26 +294,20 @@
         strncpy(motion.estop_off_snd,value,49);
         return &motion.estop_off_snd;
       } else if (strncasecmp(key,"max_head_tilt_speed",29)==0) {
-					motion.max_head_tilt_speed=atof(value);
+				motion.max_head_tilt_speed=atof(value);
+				return &motion.max_head_tilt_speed;
       } else if (strncasecmp(key,"max_head_pan_speed",29)==0) {
-					motion.max_head_pan_speed=atof(value);
+				motion.max_head_pan_speed=atof(value);
+				return &motion.max_head_pan_speed;
       } else if (strncasecmp(key,"max_head_roll_speed",29)==0) {
-					motion.max_head_roll_speed=atof(value);
-      }
-      break;
-    case sec_worldmodel2:
-      if (strncasecmp(key,"dm_port",29)==0) {
-        worldmodel2.dm_port = atoi(value);
-        return &worldmodel2.dm_port ;
-      } else if (strncasecmp(key,"hm_port",29)==0) {
-        worldmodel2.hm_port = atoi(value);
-        return &worldmodel2.hm_port ;
-      } else if (strncasecmp(key,"gm_port",29)==0) {
-        worldmodel2.gm_port = atoi(value);
-        return &worldmodel2.gm_port ;
-      } else if (strncasecmp(key,"fs_port",29)==0) {
-        worldmodel2.fs_port = atoi(value);
-        return &worldmodel2.fs_port ;
+				motion.max_head_roll_speed=atof(value);
+				return &motion.max_head_roll_speed;
+      } else if (strncasecmp(key,"console_port",29)==0) {
+        motion.console_port = atoi(value);
+        return &motion.console_port;
+      } else if (strncasecmp(key,"stderr_port",29)==0) {
+        motion.stderr_port = atoi(value);
+        return &motion.stderr_port ;
       }
       break;
     case sec_sound:
@@ -321,8 +356,6 @@
     return sec_controller;
   } else if (strncasecmp(key,"motion",29)==0) {
     return sec_motion;
-  } else if (strncasecmp(key,"worldmodel2",29)==0) {
-    return sec_worldmodel2;
   } else if (strncasecmp(key,"sound",29)==0) {
     return sec_sound;
   } else {
@@ -338,12 +371,29 @@
 
 	bool ignoring=false;
 	std::vector<std::string> curmodel;
+#ifdef PLATFORM_APERIOS
 	char rdStr[orobotdesignNAME_MAX];
 	memset(rdStr, 0, sizeof(rdStr));
 	if (OPENR::GetRobotDesign(rdStr) != oSUCCESS) {
 		printf("OPENR::GetRobotDesign() failed.\n");
 		rdStr[0]='\0';
 	}
+#else
+#  if TGT_ERS7
+	char rdStr[]="ERS-7";
+#  elif TGT_ERS210
+	char rdStr[]="ERS-210";
+#  elif TGT_ERS220
+	char rdStr[]="ERS-220";
+#  elif TGT_ERS2xx
+#    warning "TGT_2xx is not specific for simulation purposes - defaulting to ERS210"
+	char rdStr[]="ERS-210";
+#  else
+#    warning "TGT_<model> undefined - defaulting to ERS210"
+	char rdStr[]="ERS-210";
+#  endif
+#endif
+
 
 	unsigned int lineno=0;
   while (fscanf(fp,"%79[^\n]\n", buf)!=EOF) {
@@ -450,8 +500,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.30 $
+ * $Revision: 1.36 $
  * $State: Exp $
- * $Date: 2004/01/21 03:53:01 $
+ * $Date: 2004/10/11 22:01:34 $
  */
 
Index: Shared/Config.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/Config.h,v
retrieving revision 1.28
retrieving revision 1.35
diff -u -d -r1.28 -r1.35
--- Shared/Config.h	30 Jan 2004 01:30:07 -0000	1.28
+++ Shared/Config.h	11 Oct 2004 22:01:34 -0000	1.35
@@ -13,7 +13,7 @@
 	//!constructor
 	Config(const char* filename)
 		: wireless(), vision(), main(), behaviors(), controller(), motion(),
-		worldmodel2(), sound()
+		sound()
 		{ readConfig(filename); }
 	//!destructor
 	~Config() {}
@@ -26,7 +26,6 @@
 		sec_behaviors,   //!< denotes behaviors section of config file
 		sec_controller,  //!< denotes controller section of config file
 		sec_motion,      //!< denotes motion section of config file
-		sec_worldmodel2, //!< denotes worldmodel section of config file
 		sec_sound,       //!< denotes sound section of config file
 		sec_invalid      //!< denotes an invalid section of config file
 	};
@@ -44,10 +43,15 @@
 		int gain;             //!< gain
 		int shutter_speed;    //!< shutter speed
 		int resolution;       //!< resolution
+		float horizFOV;       //!< horizontal field of view of camera, in radians
+		float vertFOV;        //!< vertical field of view of camera, in radians
+		float focal_length;   //!< focal length of the camera (mm)
 		std::vector<std::string> thresh;      //!< thresholds
 		char colors[50];      //!< colors
 		int rawcam_port;      //!< port to send raw frames on
+		int rawcam_transport; //!< transport protocol: 0 for udp, 1 for tcp
 		int rle_port;         //!< port to send RLE frames on
+		int rle_transport;    //!< transport protocol: 0 for udp, 1 for tcp
 		int obj_port;         //!< port to send object info on
 		bool restore_image;   //!< if true, replaces pixels holding image info with actual image pixels (as much as possible anyway)
 		J_DCT_METHOD jpeg_dct_method;  //!< pick between dct methods for jpeg compression
@@ -74,9 +78,22 @@
     int rlecam_skip;       //!< resolution level to transmit segmented images at
     int rlecam_channel;    //!< channel of RLEGenerator to send
 		compression_t rlecam_compression; //!< what compression to use on the segmented image
+
+		//!provides a ray from camera through pixel in image
+		/*! Hopefully we'll eventually upgrade this to account for lens distortion
+		 *  @param[in] x x position in range [-1,1]
+		 *  @param[in] y y position in range [-1,1]
+		 *  @param[out] r_x x value of the ray
+		 *  @param[out] r_y y value of the ray
+		 *  @param[out] r_z z value of the ray (always 1) */
+		void computeRay(float x, float y, float& r_x, float& r_y, float& r_z) {
+			r_x=x*tan(horizFOV/2);
+			r_y=y*tan(vertFOV/2);
+			r_z=1;
+		}
       
 		//!constructor
-		vision_config() : white_balance(3), gain(2), shutter_speed(2), resolution(2), thresh(), colors(), rawcam_port(0), rle_port(0), obj_port(0), restore_image(true), jpeg_dct_method(JDCT_IFAST), rawcam_encoding(ENCODE_COLOR), rawcam_channel(0), rawcam_compression(COMPRESS_NONE), rawcam_compress_quality(75), rawcam_y_skip(0), rawcam_uv_skip(0), rlecam_skip(1), rlecam_channel(0), rlecam_compression(COMPRESS_RLE) {}
+		vision_config() : white_balance(3), gain(2), shutter_speed(2), resolution(2), horizFOV(0), vertFOV(0), focal_length(0), thresh(), colors(), rawcam_port(0), rawcam_transport(0), rle_port(0), rle_transport(0), obj_port(0), restore_image(true), jpeg_dct_method(JDCT_IFAST), rawcam_encoding(ENCODE_COLOR), rawcam_channel(0), rawcam_compression(COMPRESS_NONE), rawcam_compress_quality(75), rawcam_y_skip(0), rawcam_uv_skip(0), rlecam_skip(1), rlecam_channel(0), rlecam_compression(COMPRESS_RLE) {}
 	} vision;
 	
 	//!core functionality information
@@ -128,14 +145,18 @@
 	struct motion_config {
 		std::string root;       //!< path on memory stick to "motion" files - for instance, position (.pos) and motion sequence (.mot)
 		std::string walk;       //!< the walk parameter file to load by default for new WalkMC's
+		std::string kinematics;  //!< the kinematics description file to load
+		std::vector<std::string> kinematic_chains; //!< list of chains to load from #kinematics
 		char estop_on_snd[50];  //!< sound file to use when e-stop turned on
 		char estop_off_snd[50]; //!< sound file to use when e-stop turned off
 		float max_head_tilt_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
 		float max_head_pan_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
 		float max_head_roll_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
+		int console_port;  //!< port to send/receive "console" information on (separate from system console)
+		int stderr_port;   //!< port to send error information to
 
 		//!returns an absolute path if @a is relative (to root), otherwise just @a name
-		std::string makePath(std::string name) { 
+		std::string makePath(const std::string& name) { 
 			if(name[0]=='/')
 				return name;
 			if(root[root.size()-1]=='/')
@@ -145,7 +166,7 @@
 		}
 
 		//!constructor
-		motion_config() : root(), walk(), max_head_tilt_speed(0), max_head_pan_speed(0), max_head_roll_speed(0) {
+		motion_config() : root(), walk(), kinematics(), kinematic_chains(), max_head_tilt_speed(0), max_head_pan_speed(0), max_head_roll_speed(0), console_port(0), stderr_port(0) {
 			estop_on_snd[0]=estop_off_snd[0]='\0';
 			max_head_tilt_speed=0;
 			max_head_pan_speed=0;
@@ -153,16 +174,6 @@
 		}
 	} motion;
 
-	//!world model information
-	struct worldmodel2_config {
-		//@{
-		//!ports to use for sending world model information
-		int dm_port, hm_port, gm_port, fs_port; //@}
-
-		//!constructor
-		worldmodel2_config() : dm_port(0), hm_port(0), gm_port(0), fs_port(0) {}
-	} worldmodel2;
-	
 	//!sound information
 	struct sound_config {
 		std::string root;         //!< path to sound clips
@@ -172,7 +183,7 @@
 		std::vector<std::string> preload; //!< list of sounds to preload at boot
 			
 		//!returns an absolute path if @a is relative (to root), otherwise just @a name
-		std::string makePath(std::string name) { 
+		std::string makePath(const std::string& name) { 
 			if(name[0]=='/')
 				return name;
 			if(root[root.size()-1]=='/')
@@ -210,9 +221,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.28 $
+ * $Revision: 1.35 $
  * $State: Exp $
- * $Date: 2004/01/30 01:30:07 $
+ * $Date: 2004/10/11 22:01:34 $
  */
 
 #endif
Index: Shared/ERS210Info.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ERS210Info.h,v
retrieving revision 1.12
retrieving revision 1.18
diff -u -d -r1.12 -r1.18
--- Shared/ERS210Info.h	9 Feb 2004 22:45:28 -0000	1.12
+++ Shared/ERS210Info.h	16 Sep 2004 18:35:12 -0000	1.18
@@ -36,16 +36,6 @@
 	//!Corresponds to entries in ERS210Info::PrimitiveName, defined at the end of this file, these are the primary grouping
 	/*!Right now all binary joints are slow, but perhaps this won't always be the case... hence the IsFast/Slow bitmasks to select which type, in order to be more general */
 	//!@name Output Types Information
-	const unsigned NumPIDJoints   = 18; //!< The number of joints which use PID motion - everything except ears
-	const unsigned NumLEDs        =  9; //!< The number LEDs which can be controlled
-	const unsigned NumBinJoints   =  2; //!< The number of binary joints - just the ears
-	const unsigned NumOutputs     = NumPIDJoints + NumBinJoints + NumLEDs; //!< the total number of outputs
-
-	const bool IsFastOutput[NumOutputs] = { true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false }; //!< true for joints which can be updated every 32 ms (all but the ears)
-	//! we need this so you can tell programmatically which joints are "real" and which are "fake" in ERS-2xx target mode
-	const bool IsRealERS210[NumOutputs] = { true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true };
-	//@}
-
 	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
 	const unsigned NumLegs        =  4; //!< The number of legs
 	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
@@ -55,7 +45,18 @@
 	const unsigned NumEarJoints   =  2; //!< The number of joints which control the ears (NOT per ear, is total)
 	const unsigned NumButtons     =  8; //!< the number of buttons that are available, see ERS210Info::ButtonOffset_t
 	const unsigned NumSensors     =  1+3+1+5;  //!< 1 dist, 3 accel, 1 thermo, 5 from power, see ERS210Info::SensorOffset_t
+	const unsigned NumLEDs        =  9; //!< The number of LEDs which can be controlled
 	
+	const unsigned NumPIDJoints   = NumLegJoints+NumHeadJoints+NumTailJoints+NumMouthJoints; //!< The number of joints which use PID motion - everything except ears
+	const unsigned NumBinJoints   = NumEarJoints; //!< The number of binary joints - just the ears
+	const unsigned NumOutputs     = NumPIDJoints + NumBinJoints + NumLEDs; //!< the total number of outputs
+	const unsigned NumReferenceFrames = NumOutputs + 1 + NumLegs + 1 + 1; //!< for the base, paw, camera, and IR sensor reference frames
+
+	const bool IsFastOutput[NumOutputs] = { true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false }; //!< true for joints which can be updated every 32 ms (all but the ears)
+	//! we need this so you can tell programmatically which joints are "real" and which are "fake" in ERS-2xx target mode
+	const bool IsRealERS210[NumOutputs] = { true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true };
+	//@}
+
 
 	// *******************************
 	//         OUTPUT OFFSETS
@@ -76,6 +77,11 @@
 	const unsigned BinJointOffset = LEDOffset + NumLEDs; //!< The beginning of the binary joints
 	const unsigned EarOffset   = BinJointOffset;           //!< the offset of the beginning of the ear joints - note that ears aren't sensed.  They can be flicked by the environment and you won't know.  Nor will they be flicked back
 
+	const unsigned BaseFrameOffset   = NumOutputs; //!< Use with kinematics to refer to base reference frame
+	const unsigned PawFrameOffset    = BaseFrameOffset+1; //!< Use with kinematics to refer to paw reference frames (add appropriate LegOrder_t to specify which paw)
+	const unsigned CameraFrameOffset = PawFrameOffset+NumLegs; //!< Use with kinematics to refer to camera reference frame
+	const unsigned IRFrameOffset = CameraFrameOffset+1; //!< Use with kinematics to refer to infrared (distance) sensor reference frame
+	
 	//! The offsets of the individual legs
 	enum LegOffset_t {
 		LFrLegOffset = LegOffset+LFrLegOrder*JointsPerLeg, //!< beginning of left front leg
@@ -158,6 +164,11 @@
 		HeadFrButOffset, //!< not in reliable pressure units, but 1.0 is fairly stiff pressure, 0 is none
 		HeadBkButOffset //!< not in reliable pressure units, but 1.0 is fairly stiff pressure, 0 is none
 	};
+	
+	//! Provides a string name for each button
+	const char* const ButtonNames[NumButtons] = {
+		"LFrPaw","RFrPaw","LBkPaw","ChinBut","BackBut","HeadFrBut","HeadBkBut"
+	};
 
 	//! holds offset to different sensor values in WorldState::sensors[]
 	/*! @see WorldState::sensors[] */
@@ -459,9 +470,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.18 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/09/16 18:35:12 $
  */
 
 #endif
Index: Shared/ERS220Info.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ERS220Info.h,v
retrieving revision 1.12
retrieving revision 1.19
diff -u -d -r1.12 -r1.19
--- Shared/ERS220Info.h	9 Feb 2004 22:45:28 -0000	1.12
+++ Shared/ERS220Info.h	17 Sep 2004 18:29:54 -0000	1.19
@@ -39,10 +39,21 @@
 	//!Corresponds to entries in ERS220Info::PrimitiveName, defined at the end of this file, these are the primary grouping
 	/*!Right now all binary joints are slow, but perhaps this won't always be the case... hence the IsFast/Slow bitmasks to select which type, in order to be more general */
 	//!@name Output Types Information
-	const unsigned NumPIDJoints   = 15; //!< The number of joints which use PID motion - everything
-	const unsigned NumLEDs        = 20; //!< The number LEDs which can be controlled
-	const unsigned NumBinJoints   =  0; //!< The number of binary joints (210 has ears)
+	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
+	const unsigned NumLegs        =  4; //!< The number of legs
+	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
+	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
+	const unsigned NumTailJoints  =  0; //!< The number of joints assigned to the tail
+	const unsigned NumMouthJoints =  0; //!< the number of joints that control the mouth
+	const unsigned NumEarJoints   =  0; //!< The number of joints which control the ears (NOT per ear, is total)
+	const unsigned NumButtons     =  11; //!< the number of buttons that are available, see ERS220Info::ButtonOffset_t
+	const unsigned NumSensors     =  1+3+1+5;  //!< 1 dist, 3 accel, 1 thermo, 5 from power, see ERS220Info::SensorOffset_t
+	const unsigned NumLEDs        = 20; //!< The number of LEDs which can be controlled
+	
+	const unsigned NumPIDJoints   = NumLegJoints+NumHeadJoints+NumTailJoints+NumMouthJoints; //!< The number of joints which use PID motion - everything
+	const unsigned NumBinJoints   = NumEarJoints; //!< The number of binary joints - just the ears (which the 220 doesn't have)
 	const unsigned NumOutputs     = NumPIDJoints + NumBinJoints + NumLEDs; //!< the total number of outputs
+	const unsigned NumReferenceFrames = NumOutputs + 1 + NumLegs + 1 + 1; //!< for the base, paw, camera, and IR sensor reference frames
 
 	const bool IsFastOutput[NumOutputs] = {
 		// for PID joints
@@ -83,16 +94,6 @@
 		// for binary joints (none supported/exist on 220)
 	}; //!< true for joints which can be updated every 32 ms (all but the ears on a 210)
 
-	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
-	const unsigned NumLegs        =  4; //!< The number of legs
-	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
-	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
-	const unsigned NumTailJoints  =  0; //!< The number of joints assigned to the tail
-	const unsigned NumMouthJoints =  0; //!< the number of joints that control the mouth
-	const unsigned NumEarJoints   =  0; //!< The number of joints which control the ears (NOT per ear, is total)
-	const unsigned NumButtons     =  11; //!< the number of buttons that are available, see ERS220Info::ButtonOffset_t
-	const unsigned NumSensors     =  1+3+1+5;  //!< 1 dist, 3 accel, 1 thermo, 5 from power, see ERS220Info::SensorOffset_t
-	
 
 	// *******************************
 	//         OUTPUT OFFSETS
@@ -109,6 +110,11 @@
 
 	const unsigned BinJointOffset = NumOutputs; //!< The beginning of the binary joints
 
+	const unsigned BaseFrameOffset   = NumOutputs; //!< Use with kinematics to refer to base reference frame
+	const unsigned PawFrameOffset    = BaseFrameOffset+1; //!< Use with kinematics to refer to paw reference frames (add appropriate LegOrder_t to specify which paw)
+	const unsigned CameraFrameOffset = PawFrameOffset+NumLegs; //!< Use with kinematics to refer to camera reference frame
+	const unsigned IRFrameOffset = CameraFrameOffset+1; //!< Use with kinematics to refer to infrared (distance) sensor reference frame
+
 	//! The offsets of the individual legs
 	enum LegOffset_t {
 		LFrLegOffset = LegOffset+LFrLegOrder*JointsPerLeg, //!< beginning of left front leg
@@ -253,6 +259,11 @@
 		TailRightButOffset,
 	};
 
+	//! Provides a string name for each button
+	const char* const ButtonNames[NumButtons] = {
+		"LFrPaw","RFrPaw","LBkPaw","ChinBut","BackBut","HeadFrBut","HeadBkBut","TailLeftBut","TailCenterBut","TailRightBut"
+	};
+
 	//! holds offset to different sensor values in WorldState::sensors[]
 	/*! @see WorldState::sensors[] */
 	enum SensorOffset_t {
@@ -481,7 +492,7 @@
 			{ RAD(-117),RAD(117) },{ RAD(-11),RAD(89) },{ RAD(-27),RAD(147) }, //left back REK
 			{ RAD(-117),RAD(117) },{ RAD(-11),RAD(89) },{ RAD(-27),RAD(147) }, //right back REK
 
-			{ RAD(-82),RAD(43) },{ RAD(-89.6),RAD(89.6) },{ RAD(-29),RAD(29) }, //neck TPR
+			{ RAD(-88.5),RAD(43) },{ RAD(-89.6),RAD(89.6) },{ RAD(-29),RAD(29) }, //neck TPR
 				
 			{0,1},{0,1},{0,1},        // face left side LEDs x3
 			{0,1},{0,1},{0,1},        // face right side LEDs x3
@@ -501,7 +512,7 @@
 			{ RAD(-120),RAD(120) },{ RAD(-14),RAD(92) },{ RAD(-30),RAD(150) }, //left back jsk
 			{ RAD(-120),RAD(120) },{ RAD(-14),RAD(92) },{ RAD(-30),RAD(150) }, //right back jsk
 
-			{ RAD(-85),RAD(46) },{ RAD(-92.6),RAD(92.6) },{ RAD(-32),RAD(32) }, //neck tpr
+			{ RAD(-91.5),RAD(46) },{ RAD(-92.6),RAD(92.6) },{ RAD(-32),RAD(32) }, //neck tpr
 				
 			{0,1},{0,1},{0,1},        // face left side LEDs x3
 			{0,1},{0,1},{0,1},        // face right side LEDs x3
@@ -563,9 +574,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.19 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/09/17 18:29:54 $
  */
 
 #endif
Index: Shared/ERS2xxInfo.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ERS2xxInfo.h,v
retrieving revision 1.8
retrieving revision 1.13
diff -u -d -r1.8 -r1.13
--- Shared/ERS2xxInfo.h	9 Feb 2004 22:45:28 -0000	1.8
+++ Shared/ERS2xxInfo.h	31 Aug 2004 19:48:41 -0000	1.13
@@ -35,10 +35,21 @@
 	//!Corresponds to entries in ERS2xxInfo::PrimitiveName, defined at the end of this file, these are the primary grouping
 	/*!Right now all binary joints are slow, but perhaps this won't always be the case... hence the IsFast/Slow bitmasks to select which type, in order to be more general */
 	//!@name Output Types Information
-	const unsigned NumPIDJoints   = 18; //!< The number of joints which use PID motion - everything
-	const unsigned NumLEDs        = 22; //!< The number LEDs which can be controlled
-	const unsigned NumBinJoints   =  2; //!< The number of binary joints (210 has ears)
+	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
+	const unsigned NumLegs        =  4; //!< The number of legs
+	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
+	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
+	const unsigned NumTailJoints  =  2; //!< The number of joints assigned to the tail
+	const unsigned NumMouthJoints =  1; //!< the number of joints that control the mouth
+	const unsigned NumEarJoints   =  2; //!< The number of joints which control the ears (NOT per ear, is total)
+	const unsigned NumButtons     =  11; //!< the number of buttons that are available, see ERS2xxInfo::ButtonOffset_t
+	const unsigned NumSensors     =  1+3+1+5;  //!< 1 dist, 3 accel, 1 thermo, 5 from power, see ERS2xxInfo::SensorOffset_t
+	const unsigned NumLEDs        =  22; //!< The number of LEDs which can be controlled
+	
+	const unsigned NumPIDJoints   = NumLegJoints+NumHeadJoints+NumTailJoints+NumMouthJoints; //!< The number of joints which use PID motion - everything except ears
+	const unsigned NumBinJoints   = NumEarJoints; //!< The number of binary joints - just the ears
 	const unsigned NumOutputs     = NumPIDJoints + NumBinJoints + NumLEDs; //!< the total number of outputs
+	const unsigned NumReferenceFrames = NumOutputs + 1 + NumLegs + 1 + 1; //!< for the base, paw, camera, and IR sensor reference frames
 
 	const bool IsFastOutput[NumOutputs] = {
 		// for PID joints
@@ -111,16 +122,6 @@
 		false, false
 	}; //!< true for joints which can be updated every 32 ms (all but the ears on a 210)
 
-	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
-	const unsigned NumLegs        =  4; //!< The number of legs
-	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
-	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
-	const unsigned NumTailJoints  =  2; //!< The number of joints assigned to the tail
-	const unsigned NumMouthJoints =  1; //!< the number of joints that control the mouth
-	const unsigned NumEarJoints   =  2; //!< The number of joints which control the ears (NOT per ear, is total)
-	const unsigned NumButtons     =  11; //!< the number of buttons that are available, see ERS2xxInfo::ButtonOffset_t
-	const unsigned NumSensors     =  1+3+1+5;  //!< 1 dist, 3 accel, 1 thermo, 5 from power, see ERS2xxInfo::SensorOffset_t
-	
 
 	// *******************************
 	//         OUTPUT OFFSETS
@@ -140,6 +141,11 @@
 	const unsigned BinJointOffset = LEDOffset+NumLEDs; //!< The beginning of the binary joints
 	const unsigned EarOffset   = BinJointOffset;           //!< the offset of the beginning of the ear joints - note that ears aren't sensed.  They can be flicked by the environment and you won't know.  Nor will they be flicked back
 
+	const unsigned BaseFrameOffset   = NumOutputs; //!< Use with kinematics to refer to base reference frame
+	const unsigned PawFrameOffset    = BaseFrameOffset+1; //!< Use with kinematics to refer to paw reference frames (add appropriate LegOrder_t to specify which paw)
+	const unsigned CameraFrameOffset = PawFrameOffset+NumLegs; //!< Use with kinematics to refer to camera reference frame
+	const unsigned IRFrameOffset = CameraFrameOffset+1; //!< Use with kinematics to refer to infrared (distance) sensor reference frame
+
 	//! The offsets of the individual legs
 	enum LegOffset_t {
 		LFrLegOffset = LegOffset+LFrLegOrder*JointsPerLeg, //!< beginning of left front leg
@@ -605,9 +611,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.13 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/08/31 19:48:41 $
  */
 
 #endif
Index: Shared/ERS7Info.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ERS7Info.h,v
retrieving revision 1.9
retrieving revision 1.20
diff -u -d -r1.9 -r1.20
--- Shared/ERS7Info.h	9 Feb 2004 22:45:28 -0000	1.9
+++ Shared/ERS7Info.h	19 Oct 2004 07:37:09 -0000	1.20
@@ -29,10 +29,21 @@
 	//!Corresponds to entries in ERS7Info::PrimitiveName, defined at the end of this file, these are the primary grouping
 	/*!Right now all binary joints are slow, but perhaps this won't always be the case... hence the IsFast/Slow bitmasks to select which type, in order to be more general */
 	//!@name Output Types Information
-	const unsigned NumPIDJoints   = 18; //!< The number of joints which use PID motion - everything except ears
-	const unsigned NumLEDs        = 27; //!< The number LEDs which can be controlled
-	const unsigned NumBinJoints   =  2; //!< The number of binary joints - just the ears
+	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
+	const unsigned NumLegs        =  4; //!< The number of legs
+	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
+	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
+	const unsigned NumTailJoints  =  2; //!< The number of joints assigned to the tail
+	const unsigned NumMouthJoints =  1; //!< the number of joints that control the mouth
+	const unsigned NumEarJoints   =  2; //!< The number of joints which control the ears (NOT per ear, is total)
+	const unsigned NumButtons     =  2+4+3+1; //!< the number of buttons that are available, 2 head, 4 paws, 3 back, 1 underbelly see ERS7Info::ButtonOffset_t
+	const unsigned NumSensors     =  3+3+5;  //!< 3 IR (distance), 3 accel (force), 5 from power, see ERS7Info::SensorOffset_t
+	const unsigned NumLEDs        =  27; //!< The number of LEDs which can be controlled
+	
+	const unsigned NumPIDJoints   = NumLegJoints+NumHeadJoints+NumTailJoints+NumMouthJoints; //!< The number of joints which use PID motion - everything except ears
+	const unsigned NumBinJoints   = NumEarJoints; //!< The number of binary joints - just the ears
 	const unsigned NumOutputs     = NumPIDJoints + NumBinJoints + NumLEDs; //!< the total number of outputs
+	const unsigned NumReferenceFrames = NumOutputs + 1 + NumLegs + 1 + 3; //!< for the base, paws (NumLegs), camera, and IR sensors (3) reference frames
 
 	//! true for joints which can be updated every 32 ms (all but the ears)
 	const bool IsFastOutput[NumOutputs] = {
@@ -48,17 +59,6 @@
 	};
 	//@}
 
-	const unsigned JointsPerLeg   =  3; //!< The number of joints per leg
-	const unsigned NumLegs        =  4; //!< The number of legs
-	const unsigned NumLegJoints   =  JointsPerLeg*NumLegs; //!< the TOTAL number of joints on ALL legs
-	const unsigned NumHeadJoints  =  3; //!< The number of joints in the neck
-	const unsigned NumTailJoints  =  2; //!< The number of joints assigned to the tail
-	const unsigned NumMouthJoints =  1; //!< the number of joints that control the mouth
-	const unsigned NumEarJoints   =  2; //!< The number of joints which control the ears (NOT per ear, is total)
-	const unsigned NumButtons     =  2+4+3+1; //!< the number of buttons that are available, 2 head, 4 paws, 3 back, 1 underbelly see ERS7Info::ButtonOffset_t
-	const unsigned NumSensors     =  3+3+5;  //!< 3 IR (distance), 3 accel (force), 5 from power, see ERS7Info::SensorOffset_t
-	
-
 	// *******************************
 	//         OUTPUT OFFSETS
 	// *******************************
@@ -75,9 +75,17 @@
 
 	const unsigned LEDOffset   = PIDJointOffset + NumPIDJoints; //!< the offset of LEDs in WorldState::outputs and MotionCommand functions
 
-	const unsigned BinJointOffset = LEDOffset + NumLEDs; //!< The beginning of the binary joints
+	const unsigned BinJointOffset = LEDOffset + NumLEDs;   //!< The beginning of the binary joints
 	const unsigned EarOffset   = BinJointOffset;           //!< the offset of the beginning of the ear joints - note that ears aren't sensed.  They can be flicked by the environment and you won't know.  Nor will they be flicked back
 
+	const unsigned BaseFrameOffset   = NumOutputs; //!< Use with kinematics to refer to base reference frame
+	const unsigned PawFrameOffset    = BaseFrameOffset+1; //!< Use with kinematics to refer to paw reference frames (add appropriate LegOrder_t to specify which paw)
+	const unsigned CameraFrameOffset = PawFrameOffset+NumLegs; //!< Use with kinematics to refer to camera reference frame
+	const unsigned NearIRFrameOffset = CameraFrameOffset+1; //!< Use with kinematics to refer to short-range infrared (distance) sensor reference frame
+	const unsigned FarIRFrameOffset = NearIRFrameOffset+1; //!< Use with kinematics to refer to long-range infrared (distance) sensor reference frame
+	const unsigned ChestIRFrameOffset = FarIRFrameOffset+1; //!< Use with kinematics to refer to chest-mounted infrared (distance) sensor reference frame
+
+
 	//! The offsets of the individual legs
 	enum LegOffset_t {
 		LFrLegOffset = LegOffset+LFrLegOrder*JointsPerLeg, //!< beginning of left front leg
@@ -178,18 +186,24 @@
 		RBkPawOffset = RBkLegOrder,
 		ChinButOffset= 4,
 		HeadButOffset,
+		HeadFrButOffset=HeadButOffset,
 		FrontBackButOffset,
 		MiddleBackButOffset,
 		RearBackButOffset,
 		WirelessSwOffset
 	};
 
+	//! Provides a string name for each button
+	const char* const ButtonNames[NumButtons] = {
+		"LFrPaw","RFrPaw","LBkPaw","ChinBut","HeadBut","FrontBackBut","MiddleBackBut","RearBackBut","WirelessSw"
+	};
+
 	//! holds offset to different sensor values in WorldState::sensors[]
 	/*! @see WorldState::sensors[] */
 	enum SensorOffset_t {
-		NearIRDistOffset = 0,  //!< in millimeters
-		FarIRDistOffset,  //!< in millimeters
-		ChestIRDistOffset,  //!< in millimeters
+		NearIRDistOffset = 0,  //!< in millimeters, ranges from 50 to 500
+		FarIRDistOffset,  //!< in millimeters, ranges from 200 to 1500
+		ChestIRDistOffset,  //!< in millimeters, ranges from 100 to 900
 		BAccelOffset, //!< backward acceleration, in @f$m/s^2@f$, negative if sitting on butt (positive for faceplant)
 		LAccelOffset, //!< acceleration to the robot's left, in @f$m/s^2@f$, negative if lying on robot's left side
 		DAccelOffset, //!< downward acceleration, in @f$m/s^2@f$, negative if standing up... be careful about the signs on all of these...
@@ -354,7 +368,7 @@
 
 			{ 0x0A/(double)(1<<(16-0xE)), 0x04/(double)(1<<(16-0x2)), 0x02/(double)(1<<(16-0xF)) },
 			{ 0x08/(double)(1<<(16-0xE)), 0x02/(double)(1<<(16-0x2)), 0x04/(double)(1<<(16-0xF)) },
-			{ 0x08/(double)(1<<(16-0xE)), 0x04/(double)(1<<(16-0x2)), 0x02/(double)(1<<(16-0xF)) },
+			{ 0x08/(double)(1<<(16-0xE)), 0x08/(double)(1<<(16-0x2)), 0x02/(double)(1<<(16-0xF)) }, // 'I' value changed to 0x08 instead of standard 0x04
 
 			{ 0x0A/(double)(1<<(16-0xE)), 0x04/(double)(1<<(16-0x2)), 0x04/(double)(1<<(16-0xF)) },
 			{ 0x0A/(double)(1<<(16-0xE)), 0x04/(double)(1<<(16-0x2)), 0x04/(double)(1<<(16-0xF)) },
@@ -372,29 +386,29 @@
 	 *  These limits are <b>not</b> enforced by the framework.  They are simply available for you to use as you see fit.
 	 *  HeadPointerMC is (as of v1.6) the only included MotionCommand to actually use these values.
 	 *  
-	 *  This is disabled for the ERS-7 until Sony gives us values to use */
+	 *  These values were obtained from the administrators of the Sony OPEN-R BBS */
 	const float MaxOutputSpeed[NumOutputs] = {
-		0,     //Legs LR,FB,REK
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
+		4.86510529e-3, //Legs LR,FB,REK
+		5.27962099e-3,
+		5.27962099e-3,
+		4.86510529e-3,
+		5.27962099e-3,
+		5.27962099e-3,
+		4.86510529e-3,
+		5.27962099e-3,
+		5.27962099e-3,
+		4.86510529e-3,
+		5.27962099e-3,
+		5.27962099e-3,
 	
-		0,     //Head TPR
-		0,
-		0,
+		3.18522588e-3, //Head TPR
+		1.00574598e-2,
+		5.78140315e-3,
 	
-		0,     //Tail
-		0,
+		1.51625479e-2, //Tail
+		1.51625479e-2,
 	
-		0,     //Mouth
+		1.01447263e-2, //Mouth
 		
 		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //LEDs
 		
@@ -416,8 +430,8 @@
 		{
 			{ RAD(-115),RAD(130) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //left front REK
 			{ RAD(-115),RAD(130) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //right front REK
-			{ RAD(-115),RAD(130) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //left back REK
-			{ RAD(-115),RAD(130) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //right back REK
+			{ RAD(-130),RAD(115) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //left back REK
+			{ RAD(-130),RAD(115) },{ RAD(-10),RAD(88) },{ RAD(-25),RAD(122) }, //right back REK
 
 			{ RAD(-75),RAD(0) },{ RAD(-88),RAD(88) },{ RAD(-15),RAD(45) }, //neck Tilt-pan-nod
 				
@@ -504,9 +518,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.9 $
+ * $Revision: 1.20 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/10/19 07:37:09 $
  */
 
 #endif
Index: Shared/LoadSave.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/LoadSave.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Shared/LoadSave.cc	3 Feb 2004 01:19:05 -0000	1.4
+++ Shared/LoadSave.cc	25 Mar 2004 17:07:44 -0000	1.5
@@ -132,14 +132,38 @@
 	return resp;
 }
 
+bool LoadSave::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg) {
+	if(res>0) {
+		*buf+=res;
+		*len-=res;
+		return true;
+	} else {
+		printf("%s",msg);
+		return false;
+	}
+}
+
+bool LoadSave::ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1) {
+	if(res>0) {
+		*buf+=res;
+		*len-=res;
+		return true;
+	} else {
+		printf(msg,arg1);
+		return false;
+	}
+}
+
+
+
 /*! @file
  * @brief Implements LoadSave, inherit from this to use a standard interface for loading and saving
  * @author ejt (Creator)
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2004/02/03 01:19:05 $
+ * $Date: 2004/03/25 17:07:44 $
  */
 
Index: Shared/LoadSave.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/LoadSave.h,v
retrieving revision 1.8
retrieving revision 1.11
diff -u -d -r1.8 -r1.11
--- Shared/LoadSave.h	5 Feb 2004 23:33:45 -0000	1.8
+++ Shared/LoadSave.h	8 Apr 2004 16:28:06 -0000	1.11
@@ -112,7 +112,6 @@
 	//!@name Constructors/Destructors
 	/*! @brief constructor */
 	LoadSave() {}
-	LoadSave(const char* filename) { LoadFile(filename); }
 	virtual ~LoadSave(); //!< destructor
 	//@}
 
@@ -161,8 +160,28 @@
 	virtual unsigned int SaveFileStream(FILE* f) const;
 	//@}
 
+	//! Handy for checking results from functions which manipulate the buffer
+	/*! @param res number of bytes used
+	 *  @param buf pointer to address of current place in buffer, will be incremented by @a res bytes
+	 *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
+	 *  @param msg Error to display if res is less than or equal to zero
+	 *  @return true if everything worked, false otherwise */
+	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg);
+
+	//! Handy for checking results from functions which manipulate the buffer
+	/*! This really should be rewritten to use variable number of arguments which can be passed
+	 *  directly on to printf...
+	 *  @param res number of bytes used
+	 *  @param buf pointer to address of current place in buffer, will be incremented by @a res bytes
+	 *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
+	 *  @param msg Error to display if res is less than or equal to zero
+	 *  @param arg1 An additional argument to be displayed (using %d in the @a msg); intended for things such as line number of error in file being read
+	 *  @return true if everything worked, false otherwise */
+	static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1);
+
 	//! These are for putting creator codes at the beginning of your data to check for sanity, just optional
 	//!@name Creator Utilities
+
 	/*!@brief Returns size of the creator code
 	 * @param creator a string to use for the creator
 	 * @return the size to leave for the creator code */
@@ -331,9 +350,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.8 $
+ * $Revision: 1.11 $
  * $State: Exp $
- * $Date: 2004/02/05 23:33:45 $
+ * $Date: 2004/04/08 16:28:06 $
  */
 
 #endif
Index: Shared/Profiler.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/Profiler.cc,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- Shared/Profiler.cc	16 Jan 2004 07:14:02 -0000	1.12
+++ Shared/Profiler.cc	25 Mar 2004 17:08:57 -0000	1.13
@@ -5,6 +5,7 @@
 
 float Profiler::buckets[Profiler::HistSize];
 
+#warning Note: Ignore warning on next line (sorry!)
 unsigned int Profiler::infosOffset=offsetof(ProfilerOfSize<1>,infos); //(unsigned int)(static_cast<ProfilerOfSize<1>*>(NULL)->infos);
 
 /*! Tells the profiler that this is now the active timer, so new timers will fit "under" this.\n
@@ -163,7 +164,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.12 $
+ * $Revision: 1.13 $
  * $State: Exp $
- * $Date: 2004/01/16 07:14:02 $
+ * $Date: 2004/03/25 17:08:57 $
  */
Index: Shared/ProjectInterface.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ProjectInterface.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Shared/ProjectInterface.cc	11 Dec 2003 05:49:30 -0000	1.4
+++ Shared/ProjectInterface.cc	16 Jul 2004 19:25:09 -0000	1.5
@@ -5,7 +5,7 @@
 FilterBankGenerator * ProjectInterface::defInterleavedYUVGenerator=0;
 FilterBankGenerator * ProjectInterface::defColorJPEGGenerator=0;
 FilterBankGenerator * ProjectInterface::defGrayscaleJPEGGenerator=0;
-FilterBankGenerator * ProjectInterface::defSegmentedColorGenerator=0;
+SegmentedColorGenerator * ProjectInterface::defSegmentedColorGenerator=0;
 FilterBankGenerator * ProjectInterface::defRLEGenerator=0;
 FilterBankGenerator * ProjectInterface::defRegionGenerator=0;
 
@@ -39,8 +39,8 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2003/12/11 05:49:30 $
+ * $Date: 2004/07/16 19:25:09 $
  */
 
Index: Shared/ProjectInterface.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/ProjectInterface.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Shared/ProjectInterface.h	11 Dec 2003 05:49:30 -0000	1.4
+++ Shared/ProjectInterface.h	16 Jul 2004 19:25:10 -0000	1.5
@@ -21,6 +21,7 @@
 
 class BehaviorBase;
 class FilterBankGenerator;
+class SegmentedColorGenerator;
 
 namespace ProjectInterface {
 	
@@ -37,7 +38,7 @@
 	extern FilterBankGenerator * defInterleavedYUVGenerator;
 	extern FilterBankGenerator * defColorJPEGGenerator;
 	extern FilterBankGenerator * defGrayscaleJPEGGenerator;
-	extern FilterBankGenerator * defSegmentedColorGenerator;
+	extern SegmentedColorGenerator * defSegmentedColorGenerator;
 	extern FilterBankGenerator * defRLEGenerator;
 	extern FilterBankGenerator * defRegionGenerator;
 	//@}
@@ -74,9 +75,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * $State: Exp $
- * $Date: 2003/12/11 05:49:30 $
+ * $Date: 2004/07/16 19:25:10 $
  */
 
 #endif
Index: Shared/TimeET.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/TimeET.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Shared/TimeET.h	25 Sep 2003 15:31:53 -0000	1.3
+++ Shared/TimeET.h	25 Mar 2004 17:09:18 -0000	1.4
@@ -8,7 +8,7 @@
 #include <MCOOP.h>
 //!would be defined by system - we redefine the same structure in case we're compiling for Aperios
 struct timeval {
-	unsigned int tv_sec; //!< seconds
+	time_t tv_sec; //!< seconds
 	long tv_usec;        //!< microseconds
 };
 //!would be defined by system - we redefine the same structure in case we're compiling for Aperios
@@ -77,7 +77,7 @@
 	//@{
 	//!for comparing times
   inline bool operator<(long ms) { //what if ms is negative?
-    unsigned int sec = ms/ms_per_sec;
+    time_t sec = ms/ms_per_sec;
     return tv.tv_sec<sec || tv.tv_sec==sec && tv.tv_usec<static_cast<long>((ms-sec*ms_per_sec)*us_per_ms);
   }
   inline bool operator<(double t) {
@@ -149,9 +149,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.3 $
- * $State: Rel $
- * $Date: 2003/09/25 15:31:53 $
+ * $Revision: 1.4 $
+ * $State: Exp $
+ * $Date: 2004/03/25 17:09:18 $
  */
 
 #endif
Index: Shared/WorldState.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/WorldState.cc,v
retrieving revision 1.22
retrieving revision 1.24
diff -u -d -r1.22 -r1.24
--- Shared/WorldState.cc	19 Jan 2004 20:36:48 -0000	1.22
+++ Shared/WorldState.cc	8 May 2004 03:03:32 -0000	1.24
@@ -45,6 +45,7 @@
 	memset(powerFlags,0,sizeof(unsigned int)*PowerSourceID::NumPowerSIDs);
 	memset(button_times,0,sizeof(unsigned int)*NumButtons);
 
+#ifdef PLATFORM_APERIOS
 	//Thanks Daishi:
 	char robotDesignStr[orobotdesignNAME_MAX];
 	memset(robotDesignStr, 0, sizeof(robotDesignStr));
@@ -62,6 +63,22 @@
 			robotDesign=ERS210Mask;
 		}
 	}
+#else
+# if TGT_ERS220
+	robotDesign=ERS220Mask;
+# elif TGT_ERS210
+	robotDesign=ERS210Mask;
+# elif TGT_ERS7
+	robotDesign=ERS7Mask;
+# else //default case, ERS2xx
+#	 if TGT_ERS2xx==0
+#		warning "TGT_<model> undefined - defaulting to TGT_ERS210"
+#  else
+#   warning "TGT_ERS2xx can't be determined on non-Aperios - defaulting to TGT_ERS210"
+#	 endif
+	robotDesign=ERS210Mask;
+# endif //model selection
+#endif
 }
 
 #ifdef PLATFORM_APERIOS
@@ -71,6 +88,7 @@
 void WorldState::read(OSensorFrameVectorData& sensor, EventRouter* er) {
 	curtime=get_time();
 
+	std::vector<EventBase*> evtBuf;
 	unsigned int lastFrame=sensor.GetInfo(0)->numFrames-1;
 
 	if(robotDesign&ERS210Mask) {
@@ -119,16 +137,16 @@
 		pidduties[ERS210Info::MouthOffset] = GETDUTY(ERS210Info::CPCJointMouth);
 
 		// Get foot switches
-		chkEvent(er,LFrPawOffset,GETB(ERS210Info::CPCSensorLFPaw),"LFrPaw");
-		chkEvent(er,RFrPawOffset,GETB(ERS210Info::CPCSensorRFPaw),"RFrPaw");
-		chkEvent(er,LBkPawOffset,GETB(ERS210Info::CPCSensorLHPaw),"LBkPaw");
-		chkEvent(er,RBkPawOffset,GETB(ERS210Info::CPCSensorRHPaw),"RBkPaw");
+		chkEvent(evtBuf,LFrPawOffset,GETB(ERS210Info::CPCSensorLFPaw),"LFrPaw");
+		chkEvent(evtBuf,RFrPawOffset,GETB(ERS210Info::CPCSensorRFPaw),"RFrPaw");
+		chkEvent(evtBuf,LBkPawOffset,GETB(ERS210Info::CPCSensorLHPaw),"LBkPaw");
+		chkEvent(evtBuf,RBkPawOffset,GETB(ERS210Info::CPCSensorRHPaw),"RBkPaw");
 
 		// Get buttons
-		chkEvent(er,ERS210Info::ChinButOffset,  GETB(ERS210Info::CPCSensorChinSwitch),"ChinBut");
-		chkEvent(er,ERS210Info::BackButOffset,  GETB(ERS210Info::CPCSensorBackSwitch),"BackBut");
-		chkEvent(er,ERS210Info::HeadFrButOffset,GETD(ERS210Info::CPCSensorHeadFrontPressure),"HeadFrBut");
-		chkEvent(er,ERS210Info::HeadBkButOffset,GETD(ERS210Info::CPCSensorHeadBackPressure),"HeadBkBut");
+		chkEvent(evtBuf,ERS210Info::ChinButOffset,  GETB(ERS210Info::CPCSensorChinSwitch),"ChinBut");
+		chkEvent(evtBuf,ERS210Info::BackButOffset,  GETB(ERS210Info::CPCSensorBackSwitch),"BackBut");
+		chkEvent(evtBuf,ERS210Info::HeadFrButOffset,GETD(ERS210Info::CPCSensorHeadFrontPressure),"HeadFrBut");
+		chkEvent(evtBuf,ERS210Info::HeadBkButOffset,GETD(ERS210Info::CPCSensorHeadBackPressure),"HeadBkBut");
 
 		// Get IR distance sensor
 		sensors[ERS210Info::IRDistOffset]=GETSENSOR(ERS210Info::CPCSensorPSD) / 1000.0f;
@@ -179,21 +197,21 @@
 		pidduties[HeadOffset+PanOffset ] = GETDUTY(ERS220Info::CPCJointNeckPan);
 		pidduties[HeadOffset+RollOffset] = GETDUTY(ERS220Info::CPCJointNeckRoll);
 
-	 	chkEvent(er, ERS220Info::TailLeftButOffset, GETB(ERS220Info::CPCSensorTailLeftSwitch),  "LBkBut");
-	 	chkEvent(er, ERS220Info::TailCenterButOffset, GETB(ERS220Info::CPCSensorTailCenterSwitch),"CBkBut");
-	 	chkEvent(er, ERS220Info::TailRightButOffset, GETB(ERS220Info::CPCSensorTailRightSwitch), "RBkBut");
+	 	chkEvent(evtBuf, ERS220Info::TailLeftButOffset, GETB(ERS220Info::CPCSensorTailLeftSwitch),  "LBkBut");
+	 	chkEvent(evtBuf, ERS220Info::TailCenterButOffset, GETB(ERS220Info::CPCSensorTailCenterSwitch),"CBkBut");
+	 	chkEvent(evtBuf, ERS220Info::TailRightButOffset, GETB(ERS220Info::CPCSensorTailRightSwitch), "RBkBut");
 
 		// Get foot switches
-		chkEvent(er,LFrPawOffset,GETB(ERS220Info::CPCSensorLFPaw),"LFrPaw");
-		chkEvent(er,RFrPawOffset,GETB(ERS220Info::CPCSensorRFPaw),"RFrPaw");
-		chkEvent(er,LBkPawOffset,GETB(ERS220Info::CPCSensorLHPaw),"LBkPaw");
-		chkEvent(er,RBkPawOffset,GETB(ERS220Info::CPCSensorRHPaw),"RBkPaw");
+		chkEvent(evtBuf,LFrPawOffset,GETB(ERS220Info::CPCSensorLFPaw),"LFrPaw");
+		chkEvent(evtBuf,RFrPawOffset,GETB(ERS220Info::CPCSensorRFPaw),"RFrPaw");
+		chkEvent(evtBuf,LBkPawOffset,GETB(ERS220Info::CPCSensorLHPaw),"LBkPaw");
+		chkEvent(evtBuf,RBkPawOffset,GETB(ERS220Info::CPCSensorRHPaw),"RBkPaw");
 
 		// Get buttons
-		chkEvent(er,ERS220Info::ChinButOffset,  GETB(ERS220Info::CPCSensorChinSwitch),"ChinBut");
-		chkEvent(er,ERS220Info::BackButOffset,  GETB(ERS220Info::CPCSensorBackSwitch),"BackBut");
-		chkEvent(er,ERS220Info::HeadFrButOffset,GETD(ERS220Info::CPCSensorHeadFrontPressure),"HeadFrBut");
-		chkEvent(er,ERS220Info::HeadBkButOffset,GETD(ERS220Info::CPCSensorHeadBackPressure),"HeadBkBut");
+		chkEvent(evtBuf,ERS220Info::ChinButOffset,  GETB(ERS220Info::CPCSensorChinSwitch),"ChinBut");
+		chkEvent(evtBuf,ERS220Info::BackButOffset,  GETB(ERS220Info::CPCSensorBackSwitch),"BackBut");
+		chkEvent(evtBuf,ERS220Info::HeadFrButOffset,GETD(ERS220Info::CPCSensorHeadFrontPressure),"HeadFrBut");
+		chkEvent(evtBuf,ERS220Info::HeadBkButOffset,GETD(ERS220Info::CPCSensorHeadBackPressure),"HeadBkBut");
 
 		// Get IR distance sensor
 		sensors[ERS220Info::IRDistOffset]=GETSENSOR(ERS220Info::CPCSensorPSD) / 1000.0f;
@@ -253,19 +271,19 @@
 		pidduties[ERS7Info::MouthOffset] = GETDUTY(ERS7Info::CPCJointMouth);
 
 		// Get foot switches
-		chkEvent(er,LFrPawOffset,GETB(ERS7Info::CPCSwitchLFPaw),"LFrPaw");
-		chkEvent(er,RFrPawOffset,GETB(ERS7Info::CPCSwitchRFPaw),"RFrPaw");
-		chkEvent(er,LBkPawOffset,GETB(ERS7Info::CPCSwitchLHPaw),"LBkPaw");
-		chkEvent(er,RBkPawOffset,GETB(ERS7Info::CPCSwitchRHPaw),"RBkPaw");
+		chkEvent(evtBuf,LFrPawOffset,GETB(ERS7Info::CPCSwitchLFPaw),"LFrPaw");
+		chkEvent(evtBuf,RFrPawOffset,GETB(ERS7Info::CPCSwitchRFPaw),"RFrPaw");
+		chkEvent(evtBuf,LBkPawOffset,GETB(ERS7Info::CPCSwitchLHPaw),"LBkPaw");
+		chkEvent(evtBuf,RBkPawOffset,GETB(ERS7Info::CPCSwitchRHPaw),"RBkPaw");
 
 		// Get buttons/switches
 		// the sensors are scaled to be relatively similar to the pressure values given by the head on the 210
-		chkEvent(er, ERS7Info::ChinButOffset,       GETSENSOR(ERS7Info::CPCSwitchChin),      "ChinBut");
-		chkEvent(er, ERS7Info::HeadButOffset,       GETSENSOR(ERS7Info::CPCSensorHead)/120,      "HeadBut");
-	 	chkEvent(er, ERS7Info::FrontBackButOffset,  GETSENSOR(ERS7Info::CPCSensorBackFront)/150, "BkFrBut");
-	 	chkEvent(er, ERS7Info::MiddleBackButOffset, GETSENSOR(ERS7Info::CPCSensorBackMiddle)/150,"BkMdBut");
-	 	chkEvent(er, ERS7Info::RearBackButOffset,   GETSENSOR(ERS7Info::CPCSensorBackRear)/150,  "BkRrBut");
-	 	chkEvent(er, ERS7Info::WirelessSwOffset,GETSENSOR(ERS7Info::CPCSwitchWireless),  "WirelessSw");
+		chkEvent(evtBuf, ERS7Info::ChinButOffset,       GETSENSOR(ERS7Info::CPCSwitchChin),      "ChinBut");
+		chkEvent(evtBuf, ERS7Info::HeadButOffset,       GETSENSOR(ERS7Info::CPCSensorHead)/120,      "HeadBut");
+	 	chkEvent(evtBuf, ERS7Info::FrontBackButOffset,  GETSENSOR(ERS7Info::CPCSensorBackFront)/150, "BkFrBut");
+	 	chkEvent(evtBuf, ERS7Info::MiddleBackButOffset, GETSENSOR(ERS7Info::CPCSensorBackMiddle)/150,"BkMdBut");
+	 	chkEvent(evtBuf, ERS7Info::RearBackButOffset,   GETSENSOR(ERS7Info::CPCSensorBackRear)/150,  "BkRrBut");
+	 	chkEvent(evtBuf, ERS7Info::WirelessSwOffset,GETSENSOR(ERS7Info::CPCSwitchWireless),  "WirelessSw");
 
 		// Get IR distance sensor
 		sensors[ERS7Info::NearIRDistOffset] = GETSENSOR(ERS7Info::CPCSensorNearPSD) / 1000.0f;
@@ -280,6 +298,9 @@
 
 	unsigned int dif=curtime-lastSensorUpdateTime;
 	lastSensorUpdateTime=curtime;
+	for(unsigned int i=0; i<evtBuf.size(); i++)
+		er->postEvent(evtBuf[i]);
+	//we don't delete the events in evtBuf - we're handing them off to erouter, which will delete them itself
 	er->postEvent(EventBase::sensorEGID,SensorSourceID::UpdatedSID,EventBase::statusETID,dif);
 }
 
@@ -358,20 +379,20 @@
 
 #endif //PLATFORM_APERIOS
 
-void WorldState::chkEvent(EventRouter* er, unsigned int sid, float newval, const char* name) {
+void WorldState::chkEvent(std::vector<EventBase*>& evtBuf, unsigned int sid, float newval, const char* name) {
 	if(newval>=0.1) { //now on
 		if(buttons[sid]<0.1) { //was off: activation
-			er->postEvent(EventBase::buttonEGID,sid,EventBase::activateETID,0,name,newval);
+			evtBuf.push_back(new EventBase(EventBase::buttonEGID,sid,EventBase::activateETID,0,name,newval));
 			button_times[sid]=curtime;
 		} else if(alwaysGenerateStatus || buttons[sid]!=newval) { //already on - always or change? : status
 			unsigned int dur=curtime-button_times[sid];
-			er->postEvent(EventBase::buttonEGID,sid,EventBase::statusETID,dur,name,newval);
+			evtBuf.push_back(new EventBase(EventBase::buttonEGID,sid,EventBase::statusETID,dur,name,newval));
 		}
 	} else { //now off
 		if(buttons[sid]>=0.1) { //was on: deactivation
 			unsigned int dur=curtime-button_times[sid];
 			button_times[sid]=0;
-			er->postEvent(EventBase::buttonEGID,sid,EventBase::deactivateETID,dur,name,0);
+			evtBuf.push_back(new EventBase(EventBase::buttonEGID,sid,EventBase::deactivateETID,dur,name,0));
 		}
 	}
 	//update value
@@ -384,7 +405,7 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.22 $
+ * $Revision: 1.24 $
  * $State: Exp $
- * $Date: 2004/01/19 20:36:48 $
+ * $Date: 2004/05/08 03:03:32 $
  */
Index: Shared/WorldState.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Shared/WorldState.h,v
retrieving revision 1.25
retrieving revision 1.28
diff -u -d -r1.25 -r1.28
--- Shared/WorldState.h	9 Feb 2004 22:45:28 -0000	1.25
+++ Shared/WorldState.h	27 Jul 2004 14:36:50 -0000	1.28
@@ -14,8 +14,10 @@
 #include "Events/EventBase.h"
 #include "Shared/Profiler.h"
 #include <math.h>
+#include <vector>
 
 class EventRouter;
+class EventBase;
 
 //The following SourceIDs are for events created by WorldState's event generators
 
@@ -103,7 +105,9 @@
  * WorldState takes power and sensor updates from the system and
  * maintains the last known values in its member fields.  It throws
  * events when some of these values change, listed in the
- * ButtonSourceID, SensorSourceID, and PowerSourceID namespaces.
+ * SensorSourceID, PowerSourceID namespaces, and the ButtonOffset_t
+ * enumeration for your robot model's info
+ * namespace. (e.g. ERS210Info::ButtonOffset_t)
  *
  * Status events for buttons only generated if the
  * WorldState::alwaysGenerateStatus flag is turned on, otherwise, by
@@ -124,9 +128,9 @@
 	float pids[NumPIDJoints][3];   //!< current PID settings (same ordering as the #outputs)
 	float pidduties[NumPIDJoints]; //!< duty cycles - -1 means the motor is trying to move full power in negative direction, 1 means full power in positive direction, in practice, these values stay rather small - 0.15 is significant force. (same ordering as the #outputs)
 	
-	float vel_x; //!< the current, egocentric rate of forward locomotion
-	float vel_y; //!< the current, egocentric rate of sideways (leftward is positive) locomotion
-	float vel_a; //!< the current, egocentric rate of rotational (counterclockwise is positive) locomotion
+	float vel_x; //!< the current, egocentric rate of forward locomotion, mm/second
+	float vel_y; //!< the current, egocentric rate of sideways (leftward is positive) locomotion, mm/second
+	float vel_a; //!< the current, egocentric rate of rotational (counterclockwise is positive) locomotion, radian/second
 	unsigned int vel_time; //!< the time at which we began moving along the current velocity vector
 
 	unsigned int robotStatus;       //!< bitmask, see OPENR/OPower.h
@@ -167,7 +171,7 @@
 	unsigned int curtime; //!< set by read(OSensorFrameVectorData& sensor, EventRouter* er) for chkEvent() so each call doesn't have to
 
 	//! Tests to see if the button status has changed and post events as needed
-	void chkEvent(EventRouter* er, unsigned int off, float newval, const char* name);
+	void chkEvent(std::vector<EventBase*>& evtBuf, unsigned int off, float newval, const char* name);
 
 	//! sets the names of the flags that will be generating events
 	/*! note that this function does not actually do the event posting,
@@ -211,9 +215,9 @@
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.25 $
+ * $Revision: 1.28 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/07/27 14:36:50 $
  */
 
 #endif
Index: Shared/newmat/Makefile
===================================================================
RCS file: Shared/newmat/Makefile
diff -N Shared/newmat/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/Makefile	5 Oct 2004 04:41:02 -0000	1.7
@@ -0,0 +1,124 @@
+# Adapted from Makefile for Independent JPEG Group's software
+
+# This makefile is suitable for Unix-like systems with non-ANSI compilers.
+# If you have an ANSI compiler, makefile.ansi is a better starting point.
+
+# Read installation instructions before saying "make" !!
+
+# The name of your C compiler:
+OPENRSDK_ROOT ?= /usr/local/OPEN_R_SDK
+TEKKOTSU_ROOT ?= /usr/local/Tekkotsu
+CXX= $(OPENRSDK_ROOT)/bin/mipsel-linux-gcc
+
+# You may need to adjust these cc options:
+CXXFLAGS= -fno-inline \
+          -Wall -W -Wlarger-than-8192 -Wpointer-arith -Wcast-qual \
+          -Woverloaded-virtual -Wdeprecated -Wnon-virtual-dtor \
+          -O3 -frename-registers -fomit-frame-pointer -fno-common \
+
+#          -Wshadow -Weffc++
+
+# Link-time cc options:
+LDFLAGS=
+
+# To link any special libraries, add the necessary -l commands here.
+LDLIBS= 
+
+# miscellaneous OS-dependent stuff
+# linker
+LN= $(CC)
+# file deletion command
+RM= rm -f
+# file rename command
+MV= mv
+# library (.a) file creation command
+AR= $(OPENRSDK_ROOT)/bin/mipsel-linux-ar rc
+# second step in .a creation (use "touch" if not needed)
+AR2= $(OPENRSDK_ROOT)/bin/mipsel-linux-ranlib
+
+# End of configurable options.
+
+COLORFILT=$(TEKKOTSU_ROOT)/tools/colorfilt
+FILTERSYSWARN=$(TEKKOTSU_ROOT)/tools/filtersyswarn/filtersyswarn $(OPENRSDK_ROOT)
+
+# source files: JPEG library proper
+LIBSOURCES= bandmat.cpp cholesky.cpp evalue.cpp fft.cpp hholder.cpp \
+            jacobi.cpp myexcept.cpp newfft.cpp newmat1.cpp newmat2.cpp \
+            newmat3.cpp newmat4.cpp newmat5.cpp newmat6.cpp newmat7.cpp \
+            newmat8.cpp newmat9.cpp newmatex.cpp newmatnl.cpp newmatrm.cpp \
+            sort.cpp submat.cpp svd.cpp
+
+SOURCES= $(LIBSOURCES)
+
+# files included by source files
+INCLUDES= boolean.h include.h newmatap.h newmatio.h newmatrc.h precisio.h \
+          controlw.h myexcept.h newmat.h newmatnl.h newmatrm.h solution.h
+
+LIBOBJECTS= $(LIBSOURCES:.cpp=.o)
+# newmat1.o newmat2.o newmat3.o newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o newmat9.o newmatex.o bandmat.o submat.o myexcept.o cholesky.o evalue.o fft.o hholder.o jacobi.o newfft.o sort.o svd.o newmatrm.o newmatnl.o
+
+all: libnewmat.a
+
+.PHONY: all clean
+
+libnewmat.a: $(LIBOBJECTS)
+	$(RM) $@
+	$(AR) $@  $(LIBOBJECTS)
+	$(AR2) $@
+
+clean:
+	$(RM) *.o *.a *.log core
+
+%.o:
+	@echo "Compiling NEWMAT::$<... (Reduced warnings)"; \
+	$(CXX) $(CXXFLAGS) -o $@ -c $< > $*.log 2>&1; \
+	retval=$$?; \
+	cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+	test $$retval -eq 0; \
+
+newmat1.o:     	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.o:     	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.o:     	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.o:     	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.o:     	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.o:     	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.o:     	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.o:     	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmat9.o:     	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+
+newmatex.o:    	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.o:     	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.o:      	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.o:    	myexcept.cpp include.h myexcept.h
+
+cholesky.o:    	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.o:      	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.o:         	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.o:     	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.o:      	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.o:      	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.o:        	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.o:         	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.o:    	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmatnl.o:    	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
Index: Shared/newmat/bandmat.cpp
===================================================================
RCS file: Shared/newmat/bandmat.cpp
diff -N Shared/newmat/bandmat.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/bandmat.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,570 @@
+//$$ bandmat.cpp                     Band matrix definitions
+
+// Copyright (C) 1991,2,3,4,9: R B Davies
+
+#define WANT_MATH                    // include.h will get math fns
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,10); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+static inline int my_min(int x, int y) { return x < y ? x : y; }
+static inline int my_max(int x, int y) { return x > y ? x : y; }
+
+
+BandMatrix::BandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::BM);
+   GetMatrix(gmx); CornerClear();
+}
+
+void BandMatrix::SetParameters(const GeneralMatrix* gmx)
+{
+   REPORT
+   MatrixBandWidth bw = gmx->BandWidth();
+   lower = bw.lower; upper = bw.upper;
+}
+
+void BandMatrix::ReSize(int n, int lb, int ub)
+{
+   REPORT
+   Tracer tr("BandMatrix::ReSize");
+   if (lb<0 || ub<0) Throw(ProgramException("Undefined bandwidth"));
+   lower = (lb<=n) ? lb : n-1; upper = (ub<=n) ? ub : n-1;
+   GeneralMatrix::ReSize(n,n,n*(lower+1+upper)); CornerClear();
+}
+
+// SimpleAddOK shows when we can add etc two matrices by a simple vector add
+// and when we can add one matrix into another
+// *gm must be the same type as *this
+// return 0 if simple add is OK
+// return 1 if we can add into *gm only
+// return 2 if we can add into *this only
+// return 3 if we can't add either way
+// For SP this will still be valid if we swap 1 and 2
+
+short BandMatrix::SimpleAddOK(const GeneralMatrix* gm)
+{
+   const BandMatrix* bm = (const BandMatrix*)gm;
+   if (bm->lower == lower && bm->upper == upper) { REPORT return 0; }
+   else if (bm->lower >= lower && bm->upper >= upper) { REPORT return 1; }
+   else if (bm->lower <= lower && bm->upper <= upper) { REPORT return 2; }
+   else { REPORT return 3; }
+}
+
+short SymmetricBandMatrix::SimpleAddOK(const GeneralMatrix* gm)
+{
+   const SymmetricBandMatrix* bm = (const SymmetricBandMatrix*)gm;
+   if (bm->lower == lower) { REPORT return 0; }
+   else if (bm->lower > lower) { REPORT return 1; }
+   else { REPORT return 2; }
+}
+
+void UpperBandMatrix::ReSize(int n, int lb, int ub)
+{
+   REPORT
+   if (lb != 0)
+   {
+      Tracer tr("UpperBandMatrix::ReSize");
+      Throw(ProgramException("UpperBandMatrix with non-zero lower band" ));
+   }
+   BandMatrix::ReSize(n, lb, ub);
+}
+
+void LowerBandMatrix::ReSize(int n, int lb, int ub)
+{
+   REPORT
+   if (ub != 0)
+   {
+      Tracer tr("LowerBandMatrix::ReSize");
+      Throw(ProgramException("LowerBandMatrix with non-zero upper band" ));
+   }
+   BandMatrix::ReSize(n, lb, ub);
+}
+
+void BandMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("BandMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   MatrixBandWidth mbw = A.BandWidth();
+   ReSize(n, mbw.Lower(), mbw.Upper());
+}
+
+bool BandMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   if (Type() != A.Type()) { REPORT return false; }
+   REPORT
+   return BandWidth() == A.BandWidth();
+}
+
+void BandMatrix::ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("BandMatrix::ReSizeForAdd");
+   MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth();
+   if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
+      | (A_BW.Upper() < 0))
+         Throw(ProgramException("Can't ReSize to BandMatrix" ));
+   // already know A and B are square
+   ReSize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()),
+      my_max(A_BW.Upper(), B_BW.Upper()));
+}
+
+void BandMatrix::ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("BandMatrix::ReSizeForSP");
+   MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth();
+   if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
+      | (A_BW.Upper() < 0))
+         Throw(ProgramException("Can't ReSize to BandMatrix" ));
+   // already know A and B are square
+   ReSize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()),
+      my_min(A_BW.Upper(), B_BW.Upper()));
+}
+
+
+void BandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::BM); CornerClear();
+}
+
+void BandMatrix::CornerClear() const
+{
+   // set unused parts of BandMatrix to zero
+   REPORT
+   int i = lower; Real* s = store; int bw = lower + 1 + upper;
+   while (i)
+      { int j = i--; Real* sj = s; s += bw; while (j--) *sj++ = 0.0; }
+   i = upper; s = store + storage;
+   while (i)
+      { int j = i--; Real* sj = s; s -= bw; while (j--) *(--sj) = 0.0; }
+}
+
+MatrixBandWidth MatrixBandWidth::operator+(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower; int u = bw.upper;
+   l = (lower < 0 || l < 0) ? -1 : (lower > l) ? lower : l;
+   u = (upper < 0 || u < 0) ? -1 : (upper > u) ? upper : u;
+   return MatrixBandWidth(l,u);
+}
+
+MatrixBandWidth MatrixBandWidth::operator*(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower; int u = bw.upper;
+   l = (lower < 0 || l < 0) ? -1 : lower+l;
+   u = (upper < 0 || u < 0) ? -1 : upper+u;
+   return MatrixBandWidth(l,u);
+}
+
+MatrixBandWidth MatrixBandWidth::minimum(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower; int u = bw.upper;
+   if ((lower >= 0) && ( (l < 0) || (l > lower) )) l = lower;
+   if ((upper >= 0) && ( (u < 0) || (u > upper) )) u = upper;
+   return MatrixBandWidth(l,u);
+}
+
+UpperBandMatrix::UpperBandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UB);
+   GetMatrix(gmx); CornerClear();
+}
+
+void UpperBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::UB); CornerClear();
+}
+
+LowerBandMatrix::LowerBandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LB);
+   GetMatrix(gmx); CornerClear();
+}
+
+void LowerBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::LB); CornerClear();
+}
+
+BandLUMatrix::BandLUMatrix(const BaseMatrix& m)
+{
+   REPORT
+   Tracer tr("BandLUMatrix");
+   storage2 = 0; store2 = 0;  // in event of exception during build
+   GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate(MatrixType::BM);
+   m1 = ((BandMatrix*)gm)->lower; m2 = ((BandMatrix*)gm)->upper;
+   GetMatrix(gm);
+   if (nrows_value != ncols_value) Throw(NotSquareException(*this));
+   d = true; sing = false;
+   indx = new int [nrows_value]; MatrixErrorNoSpace(indx);
+   MONITOR_INT_NEW("Index (BndLUMat)",nrows_value,indx)
+   storage2 = nrows_value * m1;
+   store2 = new Real [storage2]; MatrixErrorNoSpace(store2);
+   MONITOR_REAL_NEW("Make (BandLUMat)",storage2,store2)
+   ludcmp();
+}
+
+BandLUMatrix::~BandLUMatrix()
+{
+   REPORT
+   MONITOR_INT_DELETE("Index (BndLUMat)",nrows_value,indx)
+   MONITOR_REAL_DELETE("Delete (BndLUMt)",storage2,store2)
+   delete [] indx; delete [] store2;
+}
+
+MatrixType BandLUMatrix::Type() const { REPORT return MatrixType::BC; }
+
+
+LogAndSign BandLUMatrix::LogDeterminant() const
+{
+   REPORT
+   if (sing) return 0.0;
+   Real* a = store; int w = m1+1+m2; LogAndSign sum; int i = nrows_value;
+   // while (i--) { sum *= *a; a += w; }
+   if (i) for (;;) { sum *= *a; if (!(--i)) break; a += w; }
+   if (!d) sum.ChangeSign(); return sum;
+}
+
+GeneralMatrix* BandMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new BandLUMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+
+void BandLUMatrix::ludcmp()
+{
+   REPORT
+   Real* a = store2; int i = storage2;
+   // clear store2 - so unused locations are always zero -
+   // required by operator==
+   while (i--) *a++ = 0.0;
+   a = store;
+   i = m1; int j = m2; int k; int n = nrows_value; int w = m1 + 1 + m2;
+   while (i)
+   {
+      Real* ai = a + i;
+      k = ++j; while (k--) *a++ = *ai++;
+      k = i--; while (k--) *a++ = 0.0;
+   }
+
+   a = store; int l = m1;
+   for (k=0; k<n; k++)
+   {
+      Real x = *a; i = k; Real* aj = a;
+      if (l < n) l++;
+      for (j=k+1; j<l; j++)
+         { aj += w; if (fabs(x) < fabs(*aj)) { x = *aj; i = j; } }
+      indx[k] = i;
+      if (x==0) { sing = true; return; }
+      if (i!=k)
+      {
+         d = !d; Real* ak = a; Real* ai = store + i * w; j = w;
+         while (j--) { x = *ak; *ak++ = *ai; *ai++ = x; }
+      }
+      aj = a + w; Real* m = store2 + m1 * k;
+      for (j=k+1; j<l; j++)
+      {
+         *m++ = x = *aj / *a; i = w; Real* ak = a;
+	 while (--i) { Real* aj1 = aj++; *aj1 = *aj - x * *(++ak); }
+         *aj++ = 0.0;
+      }
+      a += w;
+   }
+}
+
+void BandLUMatrix::lubksb(Real* B, int mini)
+{
+   REPORT
+   Tracer tr("BandLUMatrix::lubksb");
+   if (sing) Throw(SingularException(*this));
+   int n = nrows_value; int l = m1; int w = m1 + 1 + m2;
+
+   for (int k=0; k<n; k++)
+   {
+      int i = indx[k];
+      if (i!=k) { Real x=B[k]; B[k]=B[i]; B[i]=x; }
+      if (l<n) l++;
+      Real* m = store2 + k*m1; Real* b = B+k; Real* bi = b;
+      for (i=k+1; i<l; i++)  *(++bi) -= *m++ * *b;
+   }
+
+   l = -m1;
+   for (int i = n-1; i>=mini; i--)
+   {
+      Real* b = B + i; Real* bk = b; Real x = *bk;
+      Real* a = store + w*i; Real y = *a;
+      int k = l+m1; while (k--) x -=  *(++a) * *(++bk);
+      *b = x / y;
+      if (l < m2) l++;
+   }
+}
+
+void BandLUMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip; Real* el = mcin.data-i; Real* el1=el;
+   while (i--) *el++ = 0.0;
+   el += mcin.storage; i = nrows_value - mcin.skip - mcin.storage;
+   while (i--) *el++ = 0.0;
+   lubksb(el1, mcout.skip);
+}
+
+// Do we need check for entirely zero output?
+
+
+void UpperBandMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nr = mcin.skip+mcin.storage;
+   elx = mcin.data+mcin.storage; Real* el = elx;
+   int j = mcout.skip+mcout.storage-nr; i = nr-mcout.skip;
+   while (j-- > 0) *elx++ = 0.0;
+
+   Real* Ael = store + (upper+1)*(i-1)+1; j = 0;
+   if (i > 0) for(;;)
+   {
+      elx = el; Real sum = 0.0; int jx = j;
+      while (jx--) sum += *(--Ael) * *(--elx);
+      elx--; *elx = (*elx - sum) / *(--Ael);
+      if (--i <= 0) break;
+      if (j<upper) Ael -= upper - (++j); else el--;
+   }
+}
+
+void LowerBandMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
+   int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
+   while (j-- > 0) *elx++ = 0.0;
+
+   Real* el = mcin.data; Real* Ael = store + (lower+1)*nc + lower; j = 0;
+   if (i > 0) for(;;)
+   {
+      elx = el; Real sum = 0.0; int jx = j;
+      while (jx--) sum += *Ael++ * *elx++;
+      *elx = (*elx - sum) / *Ael++;
+      if (--i <= 0) break;
+      if (j<lower) Ael += lower - (++j); else el++;
+   }
+}
+
+
+LogAndSign BandMatrix::LogDeterminant() const
+{
+   REPORT
+   BandLUMatrix C(*this); return C.LogDeterminant();
+}
+
+LogAndSign LowerBandMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum;
+   Real* s = store + lower; int j = lower + 1;
+//   while (i--) { sum *= *s; s += j; }
+   if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign UpperBandMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum; Real* s = store; int j = upper + 1;
+//   while (i--) { sum *= *s; s += j; }
+   if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+GeneralMatrix* SymmetricBandMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new BandLUMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+SymmetricBandMatrix::SymmetricBandMatrix(const BaseMatrix& M)
+{
+   REPORT  // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::SB);
+   GetMatrix(gmx);
+}
+
+GeneralMatrix* SymmetricBandMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT  return Evaluate(mt); }
+
+LogAndSign SymmetricBandMatrix::LogDeterminant() const
+{
+   REPORT
+   BandLUMatrix C(*this); return C.LogDeterminant();
+}
+
+void SymmetricBandMatrix::SetParameters(const GeneralMatrix* gmx)
+{ REPORT lower = gmx->BandWidth().lower; }
+
+void SymmetricBandMatrix::ReSize(int n, int lb)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::ReSize");
+   if (lb<0) Throw(ProgramException("Undefined bandwidth"));
+   lower = (lb<=n) ? lb : n-1;
+   GeneralMatrix::ReSize(n,n,n*(lower+1));
+}
+
+void SymmetricBandMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SymmetricBandMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   MatrixBandWidth mbw = A.BandWidth(); int b = mbw.Lower();
+   if (b != mbw.Upper())
+   {
+      Tracer tr("SymmetricBandMatrix::ReSize(GM)");
+      Throw(ProgramException("Upper and lower band-widths not equal"));
+   }
+   ReSize(n, b);
+}
+
+bool SymmetricBandMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   if (Type() != A.Type()) { REPORT return false; }
+   REPORT
+   return BandWidth() == A.BandWidth();
+}
+
+void SymmetricBandMatrix::ReSizeForAdd(const GeneralMatrix& A,
+   const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::ReSizeForAdd");
+   MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth();
+   if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
+         Throw(ProgramException("Can't ReSize to SymmetricBandMatrix" ));
+   // already know A and B are square
+   ReSize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()));
+}
+
+void SymmetricBandMatrix::ReSizeForSP(const GeneralMatrix& A,
+   const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::ReSizeForSP");
+   MatrixBandWidth A_BW = A.BandWidth(); MatrixBandWidth B_BW = B.BandWidth();
+   if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
+         Throw(ProgramException("Can't ReSize to SymmetricBandMatrix" ));
+   // already know A and B are square
+   ReSize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()));
+}
+
+
+void SymmetricBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::SB);
+}
+
+void SymmetricBandMatrix::CornerClear() const
+{
+   // set unused parts of BandMatrix to zero
+   REPORT
+   int i = lower; Real* s = store; int bw = lower + 1;
+   if (i) for(;;)
+   {
+      int j = i;
+      Real* sj = s;
+      while (j--) *sj++ = 0.0;
+      if (!(--i)) break;
+      s += bw;
+   }
+}
+
+MatrixBandWidth SymmetricBandMatrix::BandWidth() const
+   { REPORT return MatrixBandWidth(lower,lower); }
+
+inline Real square(Real x) { return x*x; }
+
+
+Real SymmetricBandMatrix::SumSquare() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_value; int l=lower;
+   while (i--)
+      { int j = l; while (j--) sum2 += square(*s++); sum1 += square(*s++); }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricBandMatrix::SumAbsoluteValue() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_value; int l=lower;
+   while (i--)
+      { int j = l; while (j--) sum2 += fabs(*s++); sum1 += fabs(*s++); }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricBandMatrix::Sum() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_value; int l=lower;
+   while (i--)
+      { int j = l; while (j--) sum2 += *s++; sum1 += *s++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/boolean.h
===================================================================
RCS file: Shared/newmat/boolean.h
diff -N Shared/newmat/boolean.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/boolean.h	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,40 @@
+//$$ boolean.h                       bool class
+
+// This is for compilers that do not have bool automatically defined
+
+#ifndef bool_LIB
+#define bool_LIB 0
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+class bool
+{
+	int value;
+public:
+	bool(const int b) { value = b ? 1 : 0; }
+	bool(const void* b) { value = b ? 1 : 0; }
+	bool() {}
+	operator int() const { return value; }
+	int operator!() const { return !value; }
+};
+
+
+const bool true = 1;
+const bool false = 0;
+
+
+
+// version for some older versions of gnu g++
+//#define false 0
+//#define true 1
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
Index: Shared/newmat/cholesky.cpp
===================================================================
RCS file: Shared/newmat/cholesky.cpp
diff -N Shared/newmat/cholesky.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/cholesky.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,280 @@
+//$$ cholesky.cpp                     cholesky decomposition
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,14); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/********* Cholesky decomposition of a positive definite matrix *************/
+
+// Suppose S is symmetrix and positive definite. Then there exists a unique
+// lower triangular matrix L such that L L.t() = S;
+
+
+ReturnMatrix Cholesky(const SymmetricMatrix& S)
+{
+   REPORT
+   Tracer trace("Cholesky");
+   int nr = S.Nrows();
+   LowerTriangularMatrix T(nr);
+   Real* s = S.Store(); Real* t = T.Store(); Real* ti = t;
+   for (int i=0; i<nr; i++)
+   {
+      Real* tj = t; Real sum; int k;
+      for (int j=0; j<i; j++)
+      {
+         Real* tk = ti; sum = 0.0; k = j;
+         while (k--) { sum += *tj++ * *tk++; }
+         *tk = (*s++ - sum) / *tj++;
+      }
+      sum = 0.0; k = i;
+      while (k--) { sum += square(*ti++); }
+      Real d = *s++ - sum;
+      if (d<=0.0)  Throw(NPDException(S));
+      *ti++ = sqrt(d);
+   }
+   T.Release(); return T.ForReturn();
+}
+
+ReturnMatrix Cholesky(const SymmetricBandMatrix& S)
+{
+   REPORT
+   Tracer trace("Band-Cholesky");
+   int nr = S.Nrows(); int m = S.lower;
+   LowerBandMatrix T(nr,m);
+   Real* s = S.Store(); Real* t = T.Store(); Real* ti = t;
+
+   for (int i=0; i<nr; i++)
+   {
+      Real* tj = t; Real sum; int l;
+      if (i<m) { REPORT l = m-i; s += l; ti += l; l = i; }
+      else { REPORT t += (m+1); l = m; }
+
+      for (int j=0; j<l; j++)
+      {
+         Real* tk = ti; sum = 0.0; int k = j; tj += (m-j);
+         while (k--) { sum += *tj++ * *tk++; }
+         *tk = (*s++ - sum) / *tj++;
+      }
+      sum = 0.0;
+      while (l--) { sum += square(*ti++); }
+      Real d = *s++ - sum;
+      if (d<=0.0)  Throw(NPDException(S));
+      *ti++ = sqrt(d);
+   }
+
+   T.Release(); return T.ForReturn();
+}
+
+
+
+
+// Contributed by Nick Bennett of Schlumberger-Doll Research; modified by RBD
+
+// The enclosed routines can be used to update the Cholesky decomposition of
+// a positive definite symmetric matrix.  A good reference for this routines
+// can be found in
+// LINPACK User's Guide, Chapter 10, Dongarra et. al., SIAM, Philadelphia, 1979
+
+// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol
+void UpdateCholesky(UpperTriangularMatrix &chol, RowVector r1Modification)
+{
+   int nc = chol.Nrows();
+   ColumnVector cGivens(nc); cGivens = 0.0;
+   ColumnVector sGivens(nc); sGivens = 0.0;
+	
+   for(int j = 1; j <= nc; ++j) // process the jth column of chol
+   {
+      // apply the previous Givens rotations k = 1,...,j-1 to column j
+      for(int k = 1; k < j; ++k)
+         GivensRotation(cGivens(k), sGivens(k), chol(k,j), r1Modification(j));
+
+      // determine the jth Given's rotation
+      pythag(chol(j,j), r1Modification(j), cGivens(j), sGivens(j));
+
+      // apply the jth Given's rotation
+      {
+         Real tmp0 = cGivens(j) * chol(j,j) + sGivens(j) * r1Modification(j);
+         chol(j,j) = tmp0; r1Modification(j) = 0.0;
+      }
+
+   }
+
+}
+
+
+// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol
+void DowndateCholesky(UpperTriangularMatrix &chol, RowVector x)
+{
+   int nRC = chol.Nrows();
+	
+   // solve R^T a = x
+   LowerTriangularMatrix L = chol.t();
+   ColumnVector a(nRC); a = 0.0;
+   int i, j;
+	
+   for (i = 1; i <= nRC; ++i)
+   {
+      // accumulate subtr sum
+      Real subtrsum = 0.0;
+      for(int k = 1; k < i; ++k) subtrsum += a(k) * L(i,k);
+
+      a(i) = (x(i) - subtrsum) / L(i,i);
+   }
+
+   // test that l2 norm of a is < 1
+   Real squareNormA = a.SumSquare();
+   if (squareNormA >= 1.0)
+      Throw(ProgramException("DowndateCholesky() fails", chol));
+
+   Real alpha = sqrt(1.0 - squareNormA);
+
+   // compute and apply Givens rotations to the vector a
+   ColumnVector cGivens(nRC);  cGivens = 0.0;
+   ColumnVector sGivens(nRC);  sGivens = 0.0;
+   for(i = nRC; i >= 1; i--)
+      alpha = pythag(alpha, a(i), cGivens(i), sGivens(i));
+
+   // apply Givens rotations to the jth column of chol
+   ColumnVector xtilde(nRC); xtilde = 0.0;
+   for(j = nRC; j >= 1; j--)
+   {
+      // only the first j rotations have an affect on chol,0
+      for(int k = j; k >= 1; k--)
+         GivensRotation(cGivens(k), -sGivens(k), chol(k,j), xtilde(j));
+   }
+}
+
+
+
+// produces the Cholesky decomposition of EAE where A = chol.t() * chol
+// and E produces a RIGHT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,l,k,k+1,...l-1,l+1,...p
+void RightCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l)
+{
+   int nRC = chol.Nrows();
+   int i, j;
+	
+   // I. compute shift of column l to the kth position
+   Matrix cholCopy = chol;
+   // a. grab column l
+   ColumnVector columnL = cholCopy.Column(l);
+   // b. shift columns k,...l-1 to the RIGHT
+   for(j = l-1; j >= k; --j)
+      cholCopy.Column(j+1) = cholCopy.Column(j);
+   // c. copy the top k-1 elements of columnL into the kth column of cholCopy
+   cholCopy.Column(k) = 0.0;
+   for(i = 1; i < k; ++i) cholCopy(i,k) = columnL(i);
+
+    // II. determine the l-k Given's rotations
+   int nGivens = l-k;
+   ColumnVector cGivens(nGivens); cGivens = 0.0;
+   ColumnVector sGivens(nGivens); sGivens = 0.0;
+   for(i = l; i > k; i--)
+   {
+      int givensIndex = l-i+1;
+      columnL(i-1) = pythag(columnL(i-1), columnL(i),
+         cGivens(givensIndex), sGivens(givensIndex));
+      columnL(i) = 0.0;
+   }
+   // the kth entry of columnL is the new diagonal element in column k of cholCopy
+   cholCopy(k,k) = columnL(k);
+	
+   // III. apply these Given's rotations to subsequent columns
+   // for columns k+1,...,l-1 we only need to apply the last nGivens-(j-k) rotations
+   for(j = k+1; j <= nRC; ++j)
+   {
+      ColumnVector columnJ = cholCopy.Column(j);
+      int imin = nGivens - (j-k) + 1; if (imin < 1) imin = 1;
+      for(int gIndex = imin; gIndex <= nGivens; ++gIndex)
+      {
+         // apply gIndex Given's rotation
+         int topRowIndex = k + nGivens - gIndex;
+         GivensRotationR(cGivens(gIndex), sGivens(gIndex),
+            columnJ(topRowIndex), columnJ(topRowIndex+1));
+      }
+      cholCopy.Column(j) = columnJ;
+   }
+
+   chol << cholCopy;
+}
+
+
+
+// produces the Cholesky decomposition of EAE where A = chol.t() * chol
+// and E produces a LEFT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,k+1,...l,k,l+1,...,p to
+void LeftCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l)
+{
+   int nRC = chol.Nrows();
+   int i, j;
+
+   // I. compute shift of column k to the lth position
+   Matrix cholCopy = chol;
+   // a. grab column k
+   ColumnVector columnK = cholCopy.Column(k);
+   // b. shift columns k+1,...l to the LEFT
+   for(j = k+1; j <= l; ++j)
+      cholCopy.Column(j-1) = cholCopy.Column(j);
+   // c. copy the elements of columnK into the lth column of cholCopy
+   cholCopy.Column(l) = 0.0;
+   for(i = 1; i <= k; ++i)
+      cholCopy(i,l) = columnK(i);
+
+   // II. apply and compute Given's rotations
+   int nGivens = l-k;
+   ColumnVector cGivens(nGivens); cGivens = 0.0;
+   ColumnVector sGivens(nGivens); sGivens = 0.0;
+   for(j = k; j <= nRC; ++j)
+   {
+      ColumnVector columnJ = cholCopy.Column(j);
+
+      // apply the previous Givens rotations to columnJ
+      int imax = j - k; if (imax > nGivens) imax = nGivens;
+      for(int i = 1; i <= imax; ++i)
+      {
+         int gIndex = i;
+         int topRowIndex = k + i - 1;
+         GivensRotationR(cGivens(gIndex), sGivens(gIndex),
+            columnJ(topRowIndex), columnJ(topRowIndex+1));
+      }
+
+      // compute a new Given's rotation when j < l
+      if(j < l)
+      {
+         int gIndex = j-k+1;
+         columnJ(j) = pythag(columnJ(j), columnJ(j+1), cGivens(gIndex), sGivens(gIndex));
+         columnJ(j+1) = 0.0;
+      }
+
+      cholCopy.Column(j) = columnJ;
+   }
+
+   chol << cholCopy;
+	
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/controlw.h
===================================================================
RCS file: Shared/newmat/controlw.h
diff -N Shared/newmat/controlw.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/controlw.h	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,48 @@
+//$$ controlw.h                Control word class
+
+#ifndef CONTROL_WORD_LIB
+#define CONTROL_WORD_LIB 0
+
+// for organising an int as a series of bits which indicate whether an
+// option is on or off.
+
+class ControlWord
+{
+protected:
+   int cw;                                      // the control word
+public:
+   ControlWord() : cw(0) {}                     // do nothing
+   ControlWord(int i) : cw(i) {}                // load an integer
+
+      // select specific bits (for testing at least one set)
+   ControlWord operator*(ControlWord i) const
+      { return ControlWord(cw & i.cw); }
+   void operator*=(ControlWord i)  { cw &= i.cw; }
+
+      // set bits
+   ControlWord operator+(ControlWord i) const
+      { return ControlWord(cw | i.cw); }
+   void operator+=(ControlWord i)  { cw |= i.cw; }
+
+      // reset bits
+   ControlWord operator-(ControlWord i) const
+      { return ControlWord(cw - (cw & i.cw)); }
+   void operator-=(ControlWord i) { cw -= (cw & i.cw); }
+
+      // check if all of selected bits set or reset
+   bool operator>=(ControlWord i) const { return (cw & i.cw) == i.cw; }
+   bool operator<=(ControlWord i) const { return (cw & i.cw) == cw; }
+
+      // flip selected bits
+   ControlWord operator^(ControlWord i) const
+      { return ControlWord(cw ^ i.cw); }
+   ControlWord operator~() const { return ControlWord(~cw); }
+
+      // convert to integer
+   int operator+() const { return cw; }
+   int operator!() const { return cw==0; }
+   FREE_CHECK(ControlWord)
+};
+
+
+#endif
Index: Shared/newmat/evalue.cpp
===================================================================
RCS file: Shared/newmat/evalue.cpp
diff -N Shared/newmat/evalue.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/evalue.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,297 @@
+//$$evalue.cpp                           eigen-value decomposition
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "newmatrm.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,17); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+
+static void tred2(const SymmetricMatrix& A, DiagonalMatrix& D,
+   DiagonalMatrix& E, Matrix& Z)
+{
+   Tracer et("Evalue(tred2)");
+   REPORT
+   Real tol =
+      FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
+   int n = A.Nrows(); Z.ReSize(n,n); Z.Inject(A);
+   D.ReSize(n); E.ReSize(n);
+   Real* z = Z.Store(); int i;
+
+   for (i=n-1; i > 0; i--)                   // i=0 is excluded
+   {
+      Real f = Z.element(i,i-1); Real g = 0.0;
+      int k = i-1; Real* zik = z + i*n;
+      while (k--) g += square(*zik++);
+      Real h = g + square(f);
+      if (g <= tol) { REPORT E.element(i) = f; h = 0.0; }
+      else
+      {
+         REPORT
+         g = sign(-sqrt(h), f); E.element(i) = g; h -= f*g;
+         Z.element(i,i-1) = f-g; f = 0.0;
+         Real* zji = z + i; Real* zij = z + i*n; Real* ej = E.Store();
+         int j;
+         for (j=0; j<i; j++)
+         {
+            *zji = (*zij++)/h; g = 0.0;
+            Real* zjk = z + j*n; zik = z + i*n;
+            k = j; while (k--) g += *zjk++ * (*zik++);
+            k = i-j;
+            if (k) for(;;)
+               { g += *zjk * (*zik++); if (!(--k)) break; zjk += n; }
+            *ej++ = g/h; f += g * (*zji); zji += n;
+         }
+         Real hh = f / (h + h); zij = z + i*n; ej = E.Store();
+         for (j=0; j<i; j++)
+         {
+            f = *zij++; g = *ej - hh * f; *ej++ = g;
+            Real* zjk = z + j*n; Real* zik = z + i*n;
+            Real* ek = E.Store(); k = j+1;
+            while (k--)  *zjk++ -= ( f*(*ek++) + g*(*zik++) ); 
+         }
+      }
+      D.element(i) = h;
+   }
+
+   D.element(0) = 0.0; E.element(0) = 0.0;
+   for (i=0; i<n; i++)
+   {
+      if (D.element(i) != 0.0)
+      {
+         REPORT
+         for (int j=0; j<i; j++)
+         {
+            Real g = 0.0;
+            Real* zik = z + i*n; Real* zkj = z + j;
+            int k = i;
+            if (k) for (;;)
+               { g += *zik++ * (*zkj); if (!(--k)) break; zkj += n; }
+            Real* zki = z + i; zkj = z + j;
+            k = i;
+            if (k) for (;;)
+               { *zkj -= g * (*zki); if (!(--k)) break; zkj += n; zki += n; }
+         }
+      }
+      Real* zij = z + i*n; Real* zji = z + i;
+      int j = i;
+      if (j) for (;;)
+         { *zij++ = 0.0; *zji = 0.0; if (!(--j)) break; zji += n; }
+      D.element(i) = *zij; *zij = 1.0;
+   }
+}
+
+static void tql2(DiagonalMatrix& D, DiagonalMatrix& E, Matrix& Z)
+{
+   Tracer et("Evalue(tql2)");
+   REPORT
+   Real eps = FloatingPointPrecision::Epsilon();
+   int n = D.Nrows(); Real* z = Z.Store(); int l;
+   for (l=1; l<n; l++) E.element(l-1) = E.element(l);
+   Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
+   for (l=0; l<n; l++)
+   {
+      int i,j;
+      Real& dl = D.element(l); Real& el = E.element(l);
+      Real h = eps * ( fabs(dl) + fabs(el) );
+      if (b < h) { REPORT b = h; }
+      int m;
+      for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
+      bool test = false;
+      for (j=0; j<30; j++)
+      {
+         if (m==l) { REPORT test = true; break; }
+         Real& dl1 = D.element(l+1);
+         Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
+         dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
+         Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
+
+         p = D.element(m); Real c = 1.0; Real s = 0.0;
+         for (i=m-1; i>=l; i--)
+         {
+            Real ei = E.element(i); Real di = D.element(i);
+            Real& ei1 = E.element(i+1);
+            g = c * ei; h = c * p;
+            if ( fabs(p) >= fabs(ei))
+            {
+               REPORT
+               c = ei / p; r = sqrt(c*c + 1.0);
+               ei1 = s*p*r; s = c/r; c = 1.0/r;
+            }
+            else
+            {
+               REPORT
+               c = p / ei; r = sqrt(c*c + 1.0);
+               ei1 = s * ei * r; s = 1.0/r; c /= r;
+            }
+            p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
+
+            Real* zki = z + i; Real* zki1 = zki + 1; int k = n;
+            if (k) for (;;)
+            {
+               REPORT
+               h = *zki1; *zki1 = s*(*zki) + c*h; *zki = c*(*zki) - s*h;
+               if (!(--k)) break;
+               zki += n; zki1 += n;
+            }
+         }
+         el = s*p; dl = c*p;
+         if (fabs(el) <= b) { REPORT; test = true; break; }
+      }
+      if (!test) Throw ( ConvergenceException(D) );
+      dl += f;
+   }
+/*
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      for (int j=i+1; j<n; j++)
+         { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p; int j = n;
+         Real* zji = z + i; Real* zjk = z + k;
+         if (j) for(;;)
+         {
+            p = *zji; *zji = *zjk; *zjk = p;
+            if (!(--j)) break;
+            zji += n; zjk += n;
+         }
+      }
+   }
+*/
+}
+
+static void tred3(const SymmetricMatrix& X, DiagonalMatrix& D,
+   DiagonalMatrix& E, SymmetricMatrix& A)
+{
+   Tracer et("Evalue(tred3)");
+   REPORT
+   Real tol =
+      FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
+   int n = X.Nrows(); A = X; D.ReSize(n); E.ReSize(n);
+   Real* ei = E.Store() + n;
+   for (int i = n-1; i >= 0; i--)
+   {
+      Real h = 0.0; Real f = - FloatingPointPrecision::Maximum();
+      Real* d = D.Store(); Real* a = A.Store() + (i*(i+1))/2; int k = i;
+      while (k--) { f = *a++; *d++ = f; h += square(f); }
+      if (h <= tol) { REPORT *(--ei) = 0.0; h = 0.0; }
+      else
+      {
+         REPORT
+         Real g = sign(-sqrt(h), f); *(--ei) = g; h -= f*g;
+         f -= g; *(d-1) = f; *(a-1) = f; f = 0.0;
+         Real* dj = D.Store(); Real* ej = E.Store(); int j;
+         for (j = 0; j < i; j++)
+         {
+            Real* dk = D.Store(); Real* ak = A.Store()+(j*(j+1))/2;
+            Real g = 0.0; k = j;
+            while (k--)  g += *ak++ * *dk++;
+            k = i-j; int l = j; 
+            if (k) for (;;) { g += *ak * *dk++; if (!(--k)) break; ak += ++l; }
+            g /= h; *ej++ = g; f += g * *dj++;
+         }  
+         Real hh = f / (2 * h); Real* ak = A.Store();
+         dj = D.Store(); ej = E.Store();
+         for (j = 0; j < i; j++)
+         {
+            f = *dj++; g = *ej - hh * f; *ej++ = g;
+            Real* dk = D.Store(); Real* ek = E.Store(); k = j+1;
+            while (k--) { *ak++ -= (f * *ek++ + g * *dk++); }
+         }
+      }
+      *d = *a; *a = h;
+   }
+}
+
+static void tql1(DiagonalMatrix& D, DiagonalMatrix& E)
+{
+   Tracer et("Evalue(tql1)");
+   REPORT
+   Real eps = FloatingPointPrecision::Epsilon();
+   int n = D.Nrows(); int l;
+   for (l=1; l<n; l++) E.element(l-1) = E.element(l);
+   Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
+   for (l=0; l<n; l++)
+   {
+      int i,j;
+      Real& dl = D.element(l); Real& el = E.element(l);
+      Real h = eps * ( fabs(dl) + fabs(el) );
+      if (b < h) b = h;
+      int m;
+      for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
+      bool test = false;
+      for (j=0; j<30; j++)
+      {
+         if (m==l) { REPORT test = true; break; }
+         Real& dl1 = D.element(l+1);
+         Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
+         dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
+         Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
+
+         p = D.element(m); Real c = 1.0; Real s = 0.0;
+         for (i=m-1; i>=l; i--)
+         {
+            Real ei = E.element(i); Real di = D.element(i);
+            Real& ei1 = E.element(i+1);
+            g = c * ei; h = c * p;
+            if ( fabs(p) >= fabs(ei))
+            {
+               REPORT
+               c = ei / p; r = sqrt(c*c + 1.0);
+               ei1 = s*p*r; s = c/r; c = 1.0/r;
+            }
+            else
+            {
+               REPORT
+               c = p / ei; r = sqrt(c*c + 1.0);
+               ei1 = s * ei * r; s = 1.0/r; c /= r;
+            }
+            p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
+         }
+         el = s*p; dl = c*p;
+         if (fabs(el) <= b) { REPORT test = true; break; }
+      }
+      if (!test) Throw ( ConvergenceException(D) );
+      Real p = dl + f;
+      test = false;
+      for (i=l; i>0; i--)
+      {
+         if (p < D.element(i-1)) { REPORT D.element(i) = D.element(i-1); }
+         else { REPORT test = true; break; }
+      }
+      if (!test) i=0;
+      D.element(i) = p;
+   }
+}
+
+void EigenValues(const SymmetricMatrix& A, DiagonalMatrix& D, Matrix& Z)
+{ REPORT DiagonalMatrix E; tred2(A, D, E, Z); tql2(D, E, Z); SortSV(D,Z,true); }
+
+void EigenValues(const SymmetricMatrix& X, DiagonalMatrix& D)
+{ REPORT DiagonalMatrix E; SymmetricMatrix A; tred3(X,D,E,A); tql1(D,E); }
+
+void EigenValues(const SymmetricMatrix& X, DiagonalMatrix& D,
+   SymmetricMatrix& A)
+{ REPORT DiagonalMatrix E; tred3(X,D,E,A); tql1(D,E); }
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/fft.cpp
===================================================================
RCS file: Shared/newmat/fft.cpp
diff -N Shared/newmat/fft.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/fft.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,474 @@
+//$$ fft.cpp                         Fast fourier transform
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+
+#define WANT_MATH
+// #define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+
+// #include "newmatio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,19); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+static void cossin(int n, int d, Real& c, Real& s)
+// calculate cos(twopi*n/d) and sin(twopi*n/d)
+// minimise roundoff error
+{
+   REPORT
+   long n4 = n * 4; int sector = (int)floor( (Real)n4 / (Real)d + 0.5 );
+   n4 -= sector * d;
+   if (sector < 0) { REPORT sector = 3 - (3 - sector) % 4; }
+   else  { REPORT sector %= 4; }
+   Real ratio = 1.5707963267948966192 * (Real)n4 / (Real)d;
+
+   switch (sector)
+   {
+   case 0: REPORT c =  cos(ratio); s =  sin(ratio); break;
+   case 1: REPORT c = -sin(ratio); s =  cos(ratio); break;
+   case 2: REPORT c = -cos(ratio); s = -sin(ratio); break;
+   case 3: REPORT c =  sin(ratio); s = -cos(ratio); break;
+   }
+}
+
+static void fftstep(ColumnVector& A, ColumnVector& B, ColumnVector& X,
+   ColumnVector& Y, int after, int now, int before)
+{
+   REPORT
+   Tracer trace("FFT(step)");
+   // const Real twopi = 6.2831853071795864769;
+   const int gamma = after * before;  const int delta = now * after;
+   // const Real angle = twopi / delta;  Real temp;
+   // Real r_omega = cos(angle);  Real i_omega = -sin(angle);
+   Real r_arg = 1.0;  Real i_arg = 0.0;
+   Real* x = X.Store();  Real* y = Y.Store();   // pointers to array storage
+   const int m = A.Nrows() - gamma;
+
+   for (int j = 0; j < now; j++)
+   {
+      Real* a = A.Store(); Real* b = B.Store(); // pointers to array storage
+      Real* x1 = x; Real* y1 = y; x += after; y += after;
+      for (int ia = 0; ia < after; ia++)
+      {
+         // generate sins & cosines explicitly rather than iteratively
+         // for more accuracy; but slower
+         cossin(-(j*after+ia), delta, r_arg, i_arg);
+
+         Real* a1 = a++; Real* b1 = b++; Real* x2 = x1++; Real* y2 = y1++;
+         if (now==2)
+         {
+            REPORT int ib = before;
+            if (ib) for (;;)
+            {
+               REPORT
+               Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after;
+               Real r_value = *a2; Real i_value = *b2;
+               *x2 = r_value * r_arg - i_value * i_arg + *(a2-gamma);
+               *y2 = r_value * i_arg + i_value * r_arg + *(b2-gamma);
+               if (!(--ib)) break;
+               x2 += delta; y2 += delta;
+            }
+         }
+         else
+         {
+            REPORT int ib = before;
+            if (ib) for (;;)
+            {
+               REPORT
+               Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after;
+               Real r_value = *a2; Real i_value = *b2;
+               int in = now-1; while (in--)
+               {
+                  // it should be possible to make this faster
+                  // hand code for now = 2,3,4,5,8
+                  // use symmetry to halve number of operations
+                  a2 -= gamma; b2 -= gamma;  Real temp = r_value;
+                  r_value = r_value * r_arg - i_value * i_arg + *a2;
+                  i_value = temp    * i_arg + i_value * r_arg + *b2;
+               }
+               *x2 = r_value; *y2 = i_value;
+               if (!(--ib)) break;
+               x2 += delta; y2 += delta;
+            }
+         }
+
+         // temp = r_arg;
+         // r_arg = r_arg * r_omega - i_arg * i_omega;
+         // i_arg = temp  * i_omega + i_arg * r_omega;
+
+      }
+   }
+}
+
+
+void FFTI(const ColumnVector& U, const ColumnVector& V,
+   ColumnVector& X, ColumnVector& Y)
+{
+   // Inverse transform
+   Tracer trace("FFTI");
+   REPORT
+   FFT(U,-V,X,Y);
+   const Real n = X.Nrows(); X /= n; Y /= (-n);
+}
+
+void RealFFT(const ColumnVector& U, ColumnVector& X, ColumnVector& Y)
+{
+   // Fourier transform of a real series
+   Tracer trace("RealFFT");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n2), B(n2);
+   Real* a = A.Store(); Real* b = B.Store(); Real* u = U.Store(); int i = n2;
+   while (i--) { *a++ = *u++; *b++ = *u++; }
+   FFT(A,B,A,B);
+   int n21 = n2 + 1;
+   X.ReSize(n21); Y.ReSize(n21);
+   i = n2 - 1;
+   a = A.Store(); b = B.Store();              // first els of A and B
+   Real* an = a + i; Real* bn = b + i;        // last els of A and B
+   Real* x = X.Store(); Real* y = Y.Store();  // first els of X and Y
+   Real* xn = x + n2; Real* yn = y + n2;      // last els of X and Y
+
+   *x++ = *a + *b; *y++ = 0.0;                // first complex element
+   *xn-- = *a++ - *b++; *yn-- = 0.0;          // last complex element
+
+   int j = -1; i = n2/2;
+   while (i--)
+   {
+      Real c,s; cossin(j--,n,c,s);
+      Real am = *a - *an; Real ap = *a++ + *an--;
+      Real bm = *b - *bn; Real bp = *b++ + *bn--;
+      Real samcbp = s * am + c * bp; Real sbpcam = s * bp - c * am;
+      *x++  =  0.5 * ( ap + samcbp); *y++  =  0.5 * ( bm + sbpcam);
+      *xn-- =  0.5 * ( ap - samcbp); *yn-- =  0.5 * (-bm + sbpcam);
+   }
+}
+
+void RealFFTI(const ColumnVector& A, const ColumnVector& B, ColumnVector& U)
+{
+   // inverse of a Fourier transform of a real series
+   Tracer trace("RealFFTI");
+   REPORT
+   const int n21 = A.Nrows();                     // length of arrays
+   if (n21 != B.Nrows() || n21 == 0)
+      Throw(ProgramException("Vector lengths unequal or zero", A, B));
+   const int n2 = n21 - 1;  const int n = 2 * n2;  int i = n2 - 1;
+
+   ColumnVector X(n2), Y(n2);
+   Real* a = A.Store(); Real* b = B.Store();  // first els of A and B
+   Real* an = a + n2;   Real* bn = b + n2;    // last els of A and B
+   Real* x = X.Store(); Real* y = Y.Store();  // first els of X and Y
+   Real* xn = x + i;    Real* yn = y + i;     // last els of X and Y
+
+   Real hn = 0.5 / n2;
+   *x++  = hn * (*a + *an);  *y++  = - hn * (*a - *an);
+   a++; an--; b++; bn--;
+   int j = -1;  i = n2/2;
+   while (i--)
+   {
+      Real c,s; cossin(j--,n,c,s);
+      Real am = *a - *an; Real ap = *a++ + *an--;
+      Real bm = *b - *bn; Real bp = *b++ + *bn--;
+      Real samcbp = s * am - c * bp; Real sbpcam = s * bp + c * am;
+      *x++  =  hn * ( ap + samcbp); *y++  =  - hn * ( bm + sbpcam);
+      *xn-- =  hn * ( ap - samcbp); *yn-- =  - hn * (-bm + sbpcam);
+   }
+   FFT(X,Y,X,Y);             // have done inverting elsewhere
+   U.ReSize(n); i = n2;
+   x = X.Store(); y = Y.Store(); Real* u = U.Store();
+   while (i--) { *u++ = *x++; *u++ = - *y++; }
+}
+
+void FFT(const ColumnVector& U, const ColumnVector& V,
+   ColumnVector& X, ColumnVector& Y)
+{
+   // from Carl de Boor (1980), Siam J Sci Stat Comput, 1 173-8
+   // but first try Sande and Gentleman
+   Tracer trace("FFT");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   if (n != V.Nrows() || n == 0)
+      Throw(ProgramException("Vector lengths unequal or zero", U, V));
+   if (n == 1) { REPORT X = U; Y = V; return; }
+
+   // see if we can use the newfft routine
+   if (!FFT_Controller::OnlyOldFFT && FFT_Controller::CanFactor(n))
+   {
+      REPORT
+      X = U; Y = V;
+      if ( FFT_Controller::ar_1d_ft(n,X.Store(),Y.Store()) ) return;
+   }
+
+   ColumnVector B = V;
+   ColumnVector A = U;
+   X.ReSize(n); Y.ReSize(n);
+   const int nextmx = 8;
+   int prime[8] = { 2,3,5,7,11,13,17,19 };
+   int after = 1; int before = n; int next = 0; bool inzee = true;
+   int now = 0; int b1;             // initialised to keep gnu happy
+
+   do
+   {
+      for (;;)
+      {
+	 if (next < nextmx) { REPORT now = prime[next]; }
+	 b1 = before / now;  if (b1 * now == before) { REPORT break; }
+	 next++; now += 2;
+      }
+      before = b1;
+
+      if (inzee) { REPORT fftstep(A, B, X, Y, after, now, before); }
+      else { REPORT fftstep(X, Y, A, B, after, now, before); }
+
+      inzee = !inzee; after *= now;
+   }
+   while (before != 1);
+
+   if (inzee) { REPORT A.Release(); X = A; B.Release(); Y = B; }
+}
+
+// Trigonometric transforms
+// see Charles Van Loan (1992) "Computational frameworks for the fast
+// Fourier transform" published by SIAM; section 4.4.
+
+void DCT_II(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete cosine transform, type II, of a real series
+   Tracer trace("DCT_II");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2; const int n4 = n * 4;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   int i = n2;
+   while (i--) { *a++ = *u++; *(--b) = *u++; }
+   ColumnVector X, Y;
+   RealFFT(A, X, Y); A.CleanUp();
+   V.ReSize(n);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *v = *x;
+   int k = 0; i = n2;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real xi = *(++x); Real yi = *(++y);
+      *(++v) = xi * c + yi * s; *(--w) = xi * s - yi * c;
+   }
+}
+
+void DCT_II_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete cosine transform, type II
+   Tracer trace("DCT_II_inverse");
+   REPORT
+   const int n = V.Nrows();                     // length of array
+   const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *x = *v; *y = 0.0;
+   int i = n2; int k = 0;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real vi = *(++v); Real wi = *(--w);
+      *(++x) = vi * c + wi * s; *(++y) = vi * s - wi * c;
+   }
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.CleanUp(); Y.CleanUp(); U.ReSize(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   i = n2;
+   while (i--) { *u++ = *a++; *u++ = *(--b); }
+}
+
+void DST_II(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete sine transform, type II, of a real series
+   Tracer trace("DST_II");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2; const int n4 = n * 4;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   int i = n2;
+   while (i--) { *a++ = *u++; *(--b) = -(*u++); }
+   ColumnVector X, Y;
+   RealFFT(A, X, Y); A.CleanUp();
+   V.ReSize(n);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *(--w) = *x;
+   int k = 0; i = n2;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real xi = *(++x); Real yi = *(++y);
+      *v++ = xi * s - yi * c; *(--w) = xi * c + yi * s;
+   }
+}
+
+void DST_II_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete sine transform, type II
+   Tracer trace("DST_II_inverse");
+   REPORT
+   const int n = V.Nrows();                     // length of array
+   const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *x = *(--w); *y = 0.0;
+   int i = n2; int k = 0;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real vi = *v++; Real wi = *(--w);
+      *(++x) = vi * s + wi * c; *(++y) = - vi * c + wi * s;
+   }
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.CleanUp(); Y.CleanUp(); U.ReSize(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   i = n2;
+   while (i--) { *u++ = *a++; *u++ = -(*(--b)); }
+}
+
+void DCT_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete cosine transform, type I
+   Tracer trace("DCT_inverse");
+   REPORT
+   const int n = V.Nrows()-1;                     // length of transform
+   const int n2 = n / 2; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store();
+   Real vi = *v++; *x++ = vi; *y++ = 0.0;
+   Real sum1 = vi / 2.0; Real sum2 = sum1; vi = *v++;
+   int i = n2-1;
+   while (i--)
+   {
+      Real vi2 = *v++; sum1 += vi2 + vi; sum2 += vi2 - vi;
+      *x++ = vi2; vi2 = *v++; *y++ = vi - vi2; vi = vi2;
+   }
+   sum1 += vi; sum2 -= vi;
+   vi = *v; *x = vi; *y = 0.0; vi /= 2.0; sum1 += vi; sum2 += vi;
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.CleanUp(); Y.CleanUp(); U.ReSize(n+1);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n;
+   i = n2; int k = 0; *u++ = sum1 / n2; *v-- = sum2 / n2;
+   while (i--)
+   {
+      Real s = sin(1.5707963267948966192 * (++k) / n2);
+      Real ai = *(++a); Real bi = *(--b);
+      Real bz = (ai - bi) / 4 / s; Real az = (ai + bi) / 2;
+      *u++ = az - bz; *v-- = az + bz;
+   }
+}
+
+void DCT(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete cosine transform, type I
+   Tracer trace("DCT");
+   REPORT
+   DCT_inverse(U, V);
+   V *= (V.Nrows()-1)/2;
+}
+
+void DST_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete sine transform, type I
+   Tracer trace("DST_inverse");
+   REPORT
+   const int n = V.Nrows()-1;                     // length of transform
+   const int n2 = n / 2; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store();
+   Real vi = *(++v); *x++ = 2 * vi; *y++ = 0.0;
+   int i = n2-1;
+   while (i--) { *y++ = *(++v); Real vi2 = *(++v); *x++ = vi2 - vi; vi = vi2; }
+   *x = -2 * vi; *y = 0.0;
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.CleanUp(); Y.CleanUp(); U.ReSize(n+1);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n;
+   i = n2; int k = 0; *u++ = 0.0; *v-- = 0.0;
+   while (i--)
+   {
+      Real s = sin(1.5707963267948966192 * (++k) / n2);
+      Real ai = *(++a); Real bi = *(--b);
+      Real az = (ai + bi) / 4 / s; Real bz = (ai - bi) / 2;
+      *u++ = az - bz; *v-- = az + bz;
+   }
+}
+
+void DST(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete sine transform, type I
+   Tracer trace("DST");
+   REPORT
+   DST_inverse(U, V);
+   V *= (V.Nrows()-1)/2;
+}
+
+// Two dimensional FFT
+void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y)
+{
+   Tracer trace("FFT2");
+   REPORT
+   int m = U.Nrows(); int n = U.Ncols();
+   if (m != V.Nrows() || n != V.Ncols() || m == 0 || n == 0)
+      Throw(ProgramException("Matrix dimensions unequal or zero", U, V));
+   X = U; Y = V;
+   int i; ColumnVector CVR; ColumnVector CVI;
+   for (i = 1; i <= m; ++i)
+   {
+      FFT(X.Row(i).t(), Y.Row(i).t(), CVR, CVI);
+      X.Row(i) = CVR.t(); Y.Row(i) = CVI.t();
+   }
+   for (i = 1; i <= n; ++i)
+   {
+      FFT(X.Column(i), Y.Column(i), CVR, CVI);
+      X.Column(i) = CVR; Y.Column(i) = CVI;
+   }
+}
+
+void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y)
+{
+   // Inverse transform
+   Tracer trace("FFT2I");
+   REPORT
+   FFT2(U,-V,X,Y);
+   const Real n = X.Nrows() * X.Ncols(); X /= n; Y /= (-n);
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/hholder.cpp
===================================================================
RCS file: Shared/newmat/hholder.cpp
diff -N Shared/newmat/hholder.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/hholder.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,335 @@
+//$$ hholder.cpp                                   QR decomposition
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,16); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/*************************** QR decompositions ***************************/
+
+inline Real square(Real x) { return x*x; }
+
+void QRZT(Matrix& X, LowerTriangularMatrix& L)
+{
+   REPORT
+	 Tracer et("QRZT(1)");
+   int n = X.Ncols(); int s = X.Nrows(); L.ReSize(s);
+   if (n == 0 || s == 0) { L = 0.0; return; }
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real sum = 0.0;
+      Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); }
+      sum = sqrt(sum);
+      if (sum == 0.0)
+      {
+         REPORT
+         k=n; while(k--) { *xi0++ = 0.0; }
+         for (int j=i; j<s; j++) L.element(j,i) = 0.0;
+      }
+      else
+      {
+         L.element(i,i) = sum;
+         Real* xj0=xi0; k=n; while(k--) { *xj0++ /= sum; }
+         for (int j=i+1; j<s; j++)
+         {
+            sum=0.0;
+            xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+            xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+            L.element(j,i) = sum;
+         }
+      }
+   }
+}
+
+void QRZT(const Matrix& X, Matrix& Y, Matrix& M)
+{
+   REPORT
+   Tracer et("QRZT(2)");
+   int n = X.Ncols(); int s = X.Nrows(); int t = Y.Nrows();
+   if (Y.Ncols() != n)
+      { Throw(ProgramException("Unequal row lengths",X,Y)); }
+   M.ReSize(t,s);
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real* xj0 = Y.Store(); Real* xi0 = xi;
+      for (int j=0; j<t; j++)
+      {
+         Real sum=0.0;
+         xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+         xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+         M.element(j,i) = sum;
+      }
+   }
+}
+
+/*
+void QRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+	Tracer et("QRZ(1)");
+	int n = X.Nrows(); int s = X.Ncols(); U.ReSize(s);
+	Real* xi0 = X.Store(); int k;
+	for (int i=0; i<s; i++)
+	{
+		Real sum = 0.0;
+		Real* xi = xi0; k=n; while(k--) { sum += square(*xi); xi+=s; }
+		sum = sqrt(sum);
+		U.element(i,i) = sum;
+		if (sum==0.0) Throw(SingularException(U));
+		Real* xj0=xi0; k=n; while(k--) { *xj0 /= sum; xj0+=s; }
+		xj0 = xi0;
+		for (int j=i+1; j<s; j++)
+		{
+			sum=0.0;
+			xi=xi0; k=n; xj0++; Real* xj=xj0;
+			while(k--) { sum += *xi * *xj; xi+=s; xj+=s; }
+			xi=xi0; k=n; xj=xj0;
+			while(k--) { *xj -= sum * *xi; xj+=s; xi+=s; }
+			U.element(i,j) = sum;
+		}
+		xi0++;
+	}
+}
+*/
+
+void QRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+   REPORT
+   Tracer et("QRZ(1)");
+   int n = X.Nrows(); int s = X.Ncols(); U.ReSize(s); U = 0.0;
+   if (n == 0 || s == 0) return;
+   Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u;
+   int j, k; int J = s; int i = s;
+   while (i--)
+   {
+      Real* xj0 = xi0; Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         u = u0; Real Xi = *xi; Real* xj = xj0;
+         j = J; while(j--) *u++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += s;
+      }
+
+      Real sum = sqrt(*u0); *u0 = sum; u = u0+1;
+      if (sum == 0.0)
+      {
+         REPORT
+         j = J - 1; while(j--) *u++ = 0.0;
+
+         xj0 = xi0++; k = n;
+         if (k) for (;;)
+         {
+            *xj0 = 0.0;
+            if (!(--k)) break;
+	          xj0 += s;
+         }
+         u0 += J--;
+      }
+      else
+      {
+         int J1 = J-1; j = J1; while(j--) *u++ /= sum;
+
+         xj0 = xi0; xi = xi0++; k = n;
+         if (k) for (;;)
+         {
+            u = u0+1; Real Xi = *xi; Real* xj = xj0;
+            Xi /= sum; *xj++ = Xi;
+            j = J1; while(j--) *xj++ -= *u++ * Xi;
+            if (!(--k)) break;
+	          xi += s; xj0 += s;
+         }
+         u0 += J--;
+      }
+   }
+}
+
+void QRZ(const Matrix& X, Matrix& Y, Matrix& M)
+{
+   REPORT
+   Tracer et("QRZ(2)");
+   int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols();
+   if (Y.Nrows() != n)
+      { Throw(ProgramException("Unequal column lengths",X,Y)); }
+   M.ReSize(s,t); M = 0;Real* m0 = M.Store(); Real* m;
+   Real* xi0 = X.Store();
+   int j, k; int i = s;
+   while (i--)
+   {
+      Real* xj0 = Y.Store(); Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         m = m0; Real Xi = *xi; Real* xj = xj0;
+         j = t; while(j--) *m++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += t;
+      }
+
+      xj0 = Y.Store(); xi = xi0++; k = n;
+      if (k) for (;;)
+      {
+         m = m0; Real Xi = *xi; Real* xj = xj0;
+         j = t; while(j--) *xj++ -= *m++ * Xi;
+         if (!(--k)) break;
+         xi += s; xj0 += t;
+      }
+      m0 += t;
+   }
+}
+
+/*
+
+void QRZ(const Matrix& X, Matrix& Y, Matrix& M)
+{
+	Tracer et("QRZ(2)");
+	int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols();
+	if (Y.Nrows() != n)
+	{ Throw(ProgramException("Unequal column lengths",X,Y)); }
+	M.ReSize(s,t);
+	Real* xi0 = X.Store(); int k;
+	for (int i=0; i<s; i++)
+	{
+		Real* xj0 = Y.Store();
+		for (int j=0; j<t; j++)
+		{
+			Real sum=0.0;
+			Real* xi=xi0; Real* xj=xj0; k=n;
+			while(k--) { sum += *xi * *xj; xi+=s; xj+=t; }
+			xi=xi0; k=n; xj=xj0++;
+			while(k--) { *xj -= sum * *xi; xj+=t; xi+=s; }
+			M.element(i,j) = sum;
+		}
+		xi0++;
+	}
+}
+*/
+
+void UpdateQRZT(Matrix& X, LowerTriangularMatrix& L)
+{
+   REPORT
+	 Tracer et("UpdateQRZT");
+   int n = X.Ncols(); int s = X.Nrows();
+   if (s != L.Nrows())
+      Throw(ProgramException("Incompatible dimensions",X,L)); 
+   if (n == 0 || s == 0) return;
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real r = L.element(i,i); 
+      Real sum = 0.0;
+      Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); }
+      sum = sqrt(sum + square(r));
+      if (sum == 0.0)
+      {
+         REPORT
+         k=n; while(k--) { *xi0++ = 0.0; }
+         for (int j=i; j<s; j++) L.element(j,i) = 0.0;
+      }
+      else
+      {
+         Real frs = fabs(r) + sum;
+         Real a0 = sqrt(frs / sum); Real alpha = a0 / frs;
+         if (r <= 0) { REPORT L.element(i,i) = sum; alpha = -alpha; }
+         else { REPORT L.element(i,i) = -sum; }
+         Real* xj0=xi0; k=n; while(k--) { *xj0++ *= alpha; }
+         for (int j=i+1; j<s; j++)
+         {
+            sum = 0.0;
+            xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+            sum += a0 * L.element(j,i);
+            xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+            L.element(j,i) -= sum * a0;
+         }
+      }
+   }
+}
+
+void UpdateQRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+   REPORT
+   Tracer et("UpdateQRZ");
+   int n = X.Nrows(); int s = X.Ncols();
+   if (s != U.Ncols())
+      Throw(ProgramException("Incompatible dimensions",X,U));
+   if (n == 0 || s == 0) return; 
+   Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u;
+   RowVector V(s); Real* v0 = V.Store(); Real* v; V = 0.0;
+   int j, k; int J = s; int i = s;
+   while (i--)
+   {
+      Real* xj0 = xi0; Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         v = v0; Real Xi = *xi; Real* xj = xj0;
+         j = J; while(j--) *v++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += s;
+      }
+
+      Real r = *u0;
+      Real sum = sqrt(*v0 + square(r));
+      
+      if (sum == 0.0)
+      {
+         REPORT
+         u = u0; v = v0;
+         j = J; while(j--) { *u++ = 0.0; *v++ = 0.0; }
+         xj0 = xi0++; k = n;
+         if (k) for (;;)
+         {
+            *xj0 = 0.0;
+            if (!(--k)) break;
+	          xj0 += s;
+         }
+         u0 += J--;
+      }
+      else
+      {
+         Real frs = fabs(r) + sum;
+         Real a0 = sqrt(frs / sum); Real alpha = a0 / frs;
+         if (r <= 0) { REPORT alpha = -alpha; *u0 = sum; }
+         else { REPORT *u0 = -sum; }
+      
+         j = J - 1; v = v0 + 1; u = u0 + 1;     
+         while (j--)
+            { *v = a0 * *u + alpha * *v; *u -= a0 * *v; ++v; ++u; }
+
+         xj0 = xi0; xi = xi0++; k = n;
+         if (k) for (;;)
+         {
+            v = v0 + 1; Real Xi = *xi; Real* xj = xj0;
+            Xi *= alpha; *xj++ = Xi;
+            j = J - 1; while(j--) *xj++ -= *v++ * Xi;
+            if (!(--k)) break;
+	          xi += s; xj0 += s;
+         }
+         
+         j = J; v = v0;
+         while (j--) *v++ = 0.0;
+         
+         u0 += J--;
+      }
+   }
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/include.h
===================================================================
RCS file: Shared/newmat/include.h
diff -N Shared/newmat/include.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/include.h	2 Jul 2004 00:19:33 -0000	1.2
@@ -0,0 +1,312 @@
+//$$ include.h           include files required by various versions of C++
+
+#ifndef INCLUDE_LIB
+#define INCLUDE_LIB
+
+#define use_namespace                   // define name spaces
+
+//#define SETUP_C_SUBSCRIPTS              // allow element access via A[i][j]
+
+//#define OPT_COMPATIBLE                  // for use with opt++
+
+// Activate just one of the following 3 statements
+
+//#define SimulateExceptions              // use simulated exceptions
+#define UseExceptions                   // use C++ exceptions
+//#define DisableExceptions               // do not use exceptions
+
+
+//#define TEMPS_DESTROYED_QUICKLY         // for compilers that delete
+					// temporaries too quickly
+
+//#define TEMPS_DESTROYED_QUICKLY_R       // the same thing but applied
+					// to return from functions only
+
+//#define DO_FREE_CHECK                   // check news and deletes balance
+
+//#define USING_DOUBLE                    // elements of type double
+#define USING_FLOAT                   // elements of type float
+
+#define bool_LIB 0                      // for compatibility with my older libraries
+
+//#define ios_format_flags ios::fmtflags  // for Gnu 3 and Intel for Linux
+
+
+//#define _STANDARD_                    // using standard library
+
+//#define use_float_h                   // use float.h for precision data
+
+
+//#define HAS_INT64                     // if unsigned _int64 is recognised
+                                        // used by newran03
+                                        
+// comment out next line if Exception causes a problem
+#define TypeDefException
+
+//*********************** end of options set by user ********************
+
+
+// for Gnu C++ version 3
+#if defined __GNUG__ && __GNUG__ >= 3
+   #define _STANDARD_                   // use standard library
+   #define ios_format_flags ios::fmtflags
+#endif
+
+// for Intel C++ for Linux
+#if defined __ICC
+   #define _STANDARD_                   // use standard library
+   #define ios_format_flags ios::fmtflags
+#endif
+
+
+#ifdef _STANDARD_                       // using standard library
+   #include <cstdlib>
+   #ifdef _MSC_VER
+      #include <limits>                 // for VC++6
+   #endif
+   #ifdef WANT_STREAM
+      #include <iostream>
+      #include <iomanip>
+   #endif
+   #ifdef WANT_MATH
+      #include <cmath>
+   #endif
+   #ifdef WANT_STRING
+      #include <cstring>
+   #endif
+   #ifdef WANT_TIME
+      #include <ctime>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream>
+   #endif
+   using namespace std;
+#else
+
+#define DEFAULT_HEADER                  // use AT&T style header
+                                        // if no other compiler is recognised
+
+#ifdef _MSC_VER                         // Microsoft
+   #include <stdlib.h>
+
+//   reactivate these statements to run under MSC version 7.0
+//   typedef int jmp_buf[9];
+//   extern "C"
+//   {
+//      int __cdecl setjmp(jmp_buf);
+//      void __cdecl longjmp(jmp_buf, int);
+//   }
+
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __ZTC__                          // Zortech
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.hpp>
+      #include <iomanip.hpp>
+      #define flush ""                  // not defined in iomanip?
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#if defined __BCPLUSPLUS__ || defined __TURBOC__  // Borland or Turbo
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>            // Borland has both float and values
+                                    // but values.h returns +INF for
+                                    // MAXDOUBLE in BC5
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __GNUG__                         // Gnu C++
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __WATCOMC__                      // Watcom C/C++
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+
+#ifdef macintosh                        // MPW C++ on the Mac
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <float.h>
+#include <math.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#undef DEFAULT_HEADER
+#endif
+
+#ifdef use_float_h                      // use float.h for precision values
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <float.h>
+#include <math.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#undef DEFAULT_HEADER
+#endif
+
+
+#ifdef DEFAULT_HEADER                   // for example AT&T
+#define ATandT
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <math.h>
+#define SystemV                         // use System V
+#include <values.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#endif                                  // DEFAULT_HEADER
+
+#endif                                  // _STANDARD_
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+#ifdef USING_FLOAT                      // set precision type to float
+typedef float Real;
+typedef double long_Real;
+#endif
+
+#ifdef USING_DOUBLE                     // set precision type to double
+typedef double Real;
+typedef long double long_Real;
+#endif
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+#ifdef use_namespace
+namespace RBD_COMMON {}
+namespace RBD_LIBRARIES                 // access all my libraries
+{
+   using namespace RBD_COMMON;
+}
+#endif
+
+
+#endif
Index: Shared/newmat/jacobi.cpp
===================================================================
RCS file: Shared/newmat/jacobi.cpp
diff -N Shared/newmat/jacobi.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/jacobi.cpp	16 Jun 2004 21:16:40 -0000	1.1
@@ -0,0 +1,123 @@
+//$$jacobi.cpp                           jacobi eigenvalue analysis
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+
+//#define WANT_STREAM
+
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "precisio.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,18); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A,
+   Matrix& V, bool eivec)
+{
+   Real epsilon = FloatingPointPrecision::Epsilon();
+   Tracer et("Jacobi");
+   REPORT
+   int n = X.Nrows(); DiagonalMatrix B(n), Z(n); D.ReSize(n); A = X;
+   if (eivec) { REPORT V.ReSize(n,n); D = 1.0; V = D; }
+   B << A; D = B; Z = 0.0; A.Inject(Z);
+   bool converged = false;
+   for (int i=1; i<=50; i++)
+   {
+      Real sm=0.0; Real* a = A.Store(); int p = A.Storage();
+      while (p--) sm += fabs(*a++);            // have previously zeroed diags
+      if (sm==0.0) { REPORT converged = true; break; }
+      Real tresh = (i<4) ? 0.2 * sm / square(n) : 0.0; a = A.Store();
+      for (p = 0; p < n; p++)
+      {
+         Real* ap1 = a + (p*(p+1))/2;
+         Real& zp = Z.element(p); Real& dp = D.element(p);
+         for (int q = p+1; q < n; q++)
+         {
+            Real* ap = ap1; Real* aq = a + (q*(q+1))/2;
+            Real& zq = Z.element(q); Real& dq = D.element(q);
+            Real& apq = A.element(q,p);
+            Real g = 100 * fabs(apq); Real adp = fabs(dp); Real adq = fabs(dq);
+
+            if (i>4 && g < epsilon*adp && g < epsilon*adq) { REPORT apq = 0.0; }
+            else if (fabs(apq) > tresh)
+            {
+               REPORT
+               Real t; Real h = dq - dp; Real ah = fabs(h);
+               if (g < epsilon*ah) { REPORT t = apq / h; }
+               else
+               {
+                  REPORT
+                  Real theta = 0.5 * h / apq;
+                  t = 1.0 / ( fabs(theta) + sqrt(1.0 + square(theta)) );
+                  if (theta<0.0) { REPORT t = -t; }
+               }
+               Real c = 1.0 / sqrt(1.0 + square(t)); Real s = t * c;
+               Real tau = s / (1.0 + c); h = t * apq;
+               zp -= h; zq += h; dp -= h; dq += h; apq = 0.0;
+               int j = p;
+               while (j--)
+               {
+                  g = *ap; h = *aq;
+                  *ap++ = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau);
+               }
+               int ip = p+1; j = q-ip; ap += ip++; aq++;
+               while (j--)
+               {
+                  g = *ap; h = *aq;
+                  *ap = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau);
+                  ap += ip++;
+               }
+               if (q < n-1)             // last loop is non-empty
+               {
+                  int iq = q+1; j = n-iq; ap += ip++; aq += iq++;
+                  for (;;)
+                  {
+                     g = *ap; h = *aq;
+                     *ap = g-s*(h+g*tau); *aq = h+s*(g-h*tau);
+                     if (!(--j)) break;
+                     ap += ip++; aq += iq++;
+                  }
+               }
+               if (eivec)
+               {
+                  REPORT
+                  RectMatrixCol VP(V,p); RectMatrixCol VQ(V,q);
+                  Rotate(VP, VQ, tau, s);
+               }
+            }
+         }
+      }
+      B = B + Z; D = B; Z = 0.0;
+   }
+   if (!converged) Throw(ConvergenceException(X));
+   if (eivec) SortSV(D, V, true);
+   else SortAscending(D);
+}
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D)
+{ REPORT SymmetricMatrix A; Matrix V; Jacobi(X,D,A,V,false); }
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A)
+{ REPORT Matrix V; Jacobi(X,D,A,V,false); }
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, Matrix& V)
+{ REPORT SymmetricMatrix A; Jacobi(X,D,A,V,true); }
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/myexcept.cpp
===================================================================
RCS file: Shared/newmat/myexcept.cpp
diff -N Shared/newmat/myexcept.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/myexcept.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,484 @@
+//$$myexcept.cpp                        Exception handler
+
+// Copyright (C) 1993,4,6: R B Davies
+
+
+#define WANT_STREAM                    // include.h will get stream fns
+#define WANT_STRING
+
+#include "include.h"                   // include standard files
+
+
+#include "myexcept.h"                  // for exception handling
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+//#define REG_DEREG                    // for print out uses of new/delete
+//#define CLEAN_LIST                   // to print entries being added to
+                                       // or deleted from cleanup list
+
+#ifdef SimulateExceptions
+
+void Throw()
+{
+   for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
+      jan->CleanUp();
+   JumpItem* jx = JumpBase::jl->ji;    // previous jumpbase;
+   if ( !jx ) { Terminate(); }         // jl was initial JumpItem
+   JumpBase::jl = jx;                  // drop down a level; cannot be in front
+                                       // of previous line
+   Tracer::last = JumpBase::jl->trace;
+   longjmp(JumpBase::jl->env, 1);
+}
+
+#endif                                 // end of simulate exceptions
+
+
+unsigned long BaseException::Select;
+char* BaseException::what_error;
+int BaseException::SoFar;
+int BaseException::LastOne;
+
+BaseException::BaseException(const char* a_what)
+{
+   Select++; SoFar = 0;
+   if (!what_error)                   // make space for exception message
+   {
+      LastOne = 511;
+      what_error = new char[512];
+      if (!what_error)                // fail to make space
+      {
+         LastOne = 0;
+         what_error = (char *)"No heap space for exception message\n";
+      }
+   }
+   AddMessage("\n\nAn exception has been thrown\n");
+   AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+void BaseException::AddMessage(const char* a_what)
+{
+   if (a_what)
+   {
+      int l = strlen(a_what); int r = LastOne - SoFar;
+      if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
+      else if (r > 0)
+      {
+         strncpy(what_error+SoFar, a_what, r);
+         what_error[LastOne] = 0;
+         SoFar = LastOne;
+      }
+   }
+}
+
+void BaseException::AddInt(int value)
+{
+   bool negative;
+   if (value == 0) { AddMessage("0"); return; }
+   else if (value < 0) { value = -value; negative = true; }
+   else negative = false;
+   int n = 0; int v = value;        // how many digits will we need?
+   while (v > 0) { v /= 10; n++; }
+   if (negative) n++;
+   if (LastOne-SoFar < n) { AddMessage("***"); return; }
+
+   SoFar += n; n = SoFar; what_error[n] = 0;
+   while (value > 0)
+   {
+      int nv = value / 10; int rm = value - nv * 10;  value = nv;
+      what_error[--n] = (char)(rm + '0');
+   }
+   if (negative) what_error[--n] = '-';
+   return;
+}
+
+void Tracer::PrintTrace()
+{
+   cout << "\n";
+   for (Tracer* et = last; et; et=et->previous)
+      cout << "  * " << et->entry << "\n";
+}
+
+void Tracer::AddTrace()
+{
+   if (last)
+   {
+      BaseException::AddMessage("Trace: ");
+      BaseException::AddMessage(last->entry);
+      for (Tracer* et = last->previous; et; et=et->previous)
+      {
+         BaseException::AddMessage("; ");
+         BaseException::AddMessage(et->entry);
+      }
+      BaseException::AddMessage(".\n");
+   }
+}
+
+#ifdef SimulateExceptions
+
+
+Janitor::Janitor()
+{
+   if (do_not_link)
+   {
+      do_not_link = false; NextJanitor = 0; OnStack = false;
+#ifdef CLEAN_LIST
+      cout << "Not added to clean-list " << (unsigned long)this << "\n";
+#endif
+   }
+   else
+   {
+      OnStack = true;
+#ifdef CLEAN_LIST
+      cout << "Add to       clean-list " << (unsigned long)this << "\n";
+#endif
+      NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
+   }
+}
+
+Janitor::~Janitor()
+{
+   // expect the item to be deleted to be first on list
+   // but must be prepared to search list
+   if (OnStack)
+   {
+#ifdef CLEAN_LIST
+      cout << "Delete from  clean-list " << (unsigned long)this << "\n";
+#endif
+      Janitor* lastjan = JumpBase::jl->janitor;
+      if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
+      else
+      {
+	 for (Janitor* jan = lastjan->NextJanitor; jan;
+	    jan = lastjan->NextJanitor)
+	 {
+	    if (jan==this)
+	       { lastjan->NextJanitor = jan->NextJanitor; return; }
+	    lastjan=jan;
+	 }
+
+	 Throw(BaseException(
+"Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
+         ));
+
+
+// This message occurs when a call to ~Janitor() occurs, apparently
+// without a corresponding call to Janitor(). This could happen if my
+// way of deciding whether a constructor is being called by new
+// fails.
+
+// It may happen if you are using my simulated exceptions and also have
+// your compiler s exceptions turned on.
+
+// It can also happen if you have a class derived from Janitor
+// which does not include a copy constructor [ eg X(const &X) ].
+// Possibly also if delete is applied an object on the stack (ie not
+// called by new). Otherwise, it is a bug in myexcept or your compiler.
+// If you do not #define TEMPS_DESTROYED_QUICKLY you will get this
+// error with Microsoft C 7.0. There are probably situations where
+// you will get this when you do define TEMPS_DESTROYED_QUICKLY. This
+// is a bug in MSC. Beware of "operator" statements for defining
+// conversions; particularly for converting from a Base class to a
+// Derived class.
+
+// You may get away with simply deleting this error message and Throw
+// statement if you can not find a better way of overcoming the
+// problem. In any case please tell me if you get this error message,
+// particularly for compilers apart from Microsoft C 7.0.
+
+
+      }
+   }
+}
+
+JumpItem* JumpBase::jl;              // will be set to zero
+jmp_buf JumpBase::env;
+bool Janitor::do_not_link;           // will be set to false
+
+
+int JanitorInitializer::ref_count;
+
+JanitorInitializer::JanitorInitializer()
+{
+   if (ref_count++ == 0) new JumpItem;
+                                    // need JumpItem at head of list
+}
+
+#endif                              // end of SimulateExceptions
+
+Tracer* Tracer::last;               // will be set to zero
+
+
+void Terminate()
+{
+   cout << "\n\nThere has been an exception with no handler - exiting";
+   const char* what = BaseException::what();
+   if (what) cout << what << "\n";
+   exit(1);
+}
+
+
+
+#ifdef DO_FREE_CHECK
+// Routines for tracing whether new and delete calls are balanced
+
+FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
+   { FreeCheck::next = this; }
+
+FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
+
+FCLRealArray::FCLRealArray(void* t, char* o, int s)
+  : Operation(o), size(s) { ClassStore=t; }
+
+FCLIntArray::FCLIntArray(void* t, char* o, int s)
+  : Operation(o), size(s) { ClassStore=t; }
+
+FreeCheckLink* FreeCheck::next;
+int FreeCheck::BadDelete;
+
+void FCLClass::Report()
+{ cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
+
+void FCLRealArray::Report()
+{
+   cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
+      "   " << size << "\n";
+}
+
+void FCLIntArray::Report()
+{
+   cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
+      "   " << size << "\n";
+}
+
+void FreeCheck::Register(void* t, char* name)
+{
+   FCLClass* f = new FCLClass(t,name);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::RegisterR(void* t, char* o, int s)
+{
+   FCLRealArray* f = new FCLRealArray(t,o,s);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::RegisterI(void* t, char* o, int s)
+{
+   FCLIntArray* f = new FCLIntArray(t,o,s);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::DeRegister(void* t, char* name)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent object of class and location:\n";
+   cout << "   " << name << "   " << (unsigned long)t << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::DeRegisterR(void* t, char* o, int s)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
+	 {
+	    cout << "\nArray sizes do not agree:\n";
+	    cout << "   " << o << "   " << (unsigned long)t
+	       << "   " << ((FCLRealArray*)fcl)->size << "   " << s << "\n";
+	    Tracer::PrintTrace();
+	    cout << "\n";
+	 }
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent real array:\n";
+   cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::DeRegisterI(void* t, char* o, int s)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
+	 {
+	    cout << "\nArray sizes do not agree:\n";
+	    cout << "   " << o << "   " << (unsigned long)t
+	       << "   " << ((FCLIntArray*)fcl)->size << "   " << s << "\n";
+	    Tracer::PrintTrace();
+	    cout << "\n";
+	 }
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent int array:\n";
+   cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::Status()
+{
+   if (next)
+   {
+      cout << "\nObjects of the following classes remain undeleted:\n";
+      for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
+      cout << "\n";
+   }
+   else cout << "\nNo objects remain undeleted\n\n";
+   if (BadDelete)
+   {
+      cout << "\nThere were " << BadDelete << 
+         " requests to delete non-existent items\n\n";
+   }
+}
+
+#endif                            // end of DO_FREE_CHECK
+
+// derived exception bodies
+
+Logic_error::Logic_error(const char* a_what) : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("Logic error:- "); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Runtime_error::Runtime_error(const char* a_what)
+   : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("Runtime error:- "); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Domain_error::Domain_error(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("domain error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("invalid argument\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Length_error::Length_error(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("length error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Out_of_range::Out_of_range(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("out of range\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+//Bad_cast::Bad_cast(const char* a_what) : Logic_error()
+//{
+//   Select = BaseException::Select;
+//   AddMessage("bad cast\n"); AddMessage(a_what);
+//   if (a_what) Tracer::AddTrace();
+//}
+
+//Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
+//{
+//   Select = BaseException::Select;
+//   AddMessage("bad type id.\n"); AddMessage(a_what);
+//   if (a_what) Tracer::AddTrace();
+//}
+
+Range_error::Range_error(const char* a_what) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("range error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("overflow error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Bad_alloc::Bad_alloc(const char* a_what) : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("bad allocation\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+
+
+
+unsigned long Logic_error::Select;
+unsigned long Runtime_error::Select;
+unsigned long Domain_error::Select;
+unsigned long Invalid_argument::Select;
+unsigned long Length_error::Select;
+unsigned long Out_of_range::Select;
+//unsigned long Bad_cast::Select;
+//unsigned long Bad_typeid::Select;
+unsigned long Range_error::Select;
+unsigned long Overflow_error::Select;
+unsigned long Bad_alloc::Select;
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/myexcept.h
===================================================================
RCS file: Shared/newmat/myexcept.h
diff -N Shared/newmat/myexcept.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/myexcept.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,433 @@
+//$$ myexcept.h                                  Exception handling classes
+
+
+// A set of classes to simulate exceptions in C++
+//
+//   Partially copied from Carlos Vidal s article in the C users  journal
+//   September 1992, pp 19-28
+//
+//   Operations defined
+//      Try {     }
+//      Throw ( exception object )
+//      ReThrow
+//      Catch ( exception class ) {      }
+//      CatchAll {      }
+//      CatchAndThrow
+//
+//   All catch lists must end with a CatchAll or CatchAndThrow statement
+//   but not both.
+//
+//   When exceptions are finally implemented replace Try, Throw(E), Rethrow,
+//   Catch, CatchAll, CatchAndThrow by try, throw E, throw, catch,
+//   catch(...), and {}.
+//
+//   All exception classes must be derived from BaseException, have no
+//   non-static variables and must include the statement
+//
+//      static unsigned long Select;
+//
+//   Any constructor in one of these exception classes must include
+//
+//      Select = BaseException::Select;
+//
+//   For each exceptions class, EX_1, some .cpp file must include
+//
+//      unsigned long EX_1::Select;
+//
+
+
+#ifndef EXCEPTION_LIB
+#define EXCEPTION_LIB
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+void Terminate();
+
+
+//********** classes for setting up exceptions and reporting ************//
+
+class BaseException;
+
+class Tracer                             // linked list showing how
+{                                        // we got here
+   const char* entry;
+   Tracer* previous;
+public:
+   Tracer(const char*);
+   ~Tracer();
+   void ReName(const char*);
+   static void PrintTrace();             // for printing trace
+   static void AddTrace();               // insert trace in exception record
+   static Tracer* last;                  // points to Tracer list
+   friend class BaseException;
+};
+
+
+class BaseException                          // The base exception class
+{
+protected:
+   static char* what_error;              // error message
+   static int SoFar;                     // no. characters already entered
+   static int LastOne;                   // last location in error buffer
+public:
+   static void AddMessage(const char* a_what);
+                                         // messages about exception
+   static void AddInt(int value);        // integer to error message
+   static unsigned long Select;          // for identifying exception
+   BaseException(const char* a_what = 0);
+   static const char* what() { return what_error; }
+                                         // for getting error message
+};
+
+#ifdef TypeDefException
+typedef BaseException Exception;        // for compatibility with my older libraries
+#endif
+
+inline Tracer::Tracer(const char* e)
+   : entry(e), previous(last) { last = this; }
+
+inline Tracer::~Tracer() { last = previous; }
+
+inline void Tracer::ReName(const char* e) { entry=e; }
+
+#ifdef SimulateExceptions                // SimulateExceptions
+
+#include <setjmp.h>
+
+
+//************* the definitions of Try, Throw and Catch *****************//
+
+
+class JumpItem;
+class Janitor;
+
+class JumpBase         // pointer to a linked list of jmp_buf s
+{
+public:
+   static JumpItem *jl;
+   static jmp_buf env;
+};
+
+class JumpItem         // an item in a linked list of jmp_buf s
+{
+public:
+   JumpItem *ji;
+   jmp_buf env;
+   Tracer* trace;                     // to keep check on Tracer items
+   Janitor* janitor;                  // list of items for cleanup
+   JumpItem() : ji(JumpBase::jl), trace(0), janitor(0)
+      { JumpBase::jl = this; }
+   ~JumpItem() { JumpBase::jl = ji; }
+};
+
+void Throw();
+
+inline void Throw(const BaseException&) { Throw(); }
+
+#define Try                                             \
+   if (!setjmp( JumpBase::jl->env )) {                  \
+   JumpBase::jl->trace = Tracer::last;               \
+   JumpItem JI387256156;
+
+#define ReThrow Throw()
+
+#define Catch(EXCEPTION)                                \
+   } else if (BaseException::Select == EXCEPTION::Select) {
+
+#define CatchAll } else
+
+#define CatchAndThrow  } else Throw();
+
+
+//****************** cleanup heap following Throw ***********************//
+
+class Janitor
+{
+protected:
+   static bool do_not_link;                  // set when new is called
+   bool OnStack;                             // false if created by new
+public:
+   Janitor* NextJanitor;
+   virtual void CleanUp() {}
+   Janitor();
+   virtual ~Janitor();
+};
+
+
+// The tiresome old trick for initializing the Janitor class
+// this is needed for classes derived from Janitor which have objects
+// declared globally
+
+class JanitorInitializer
+{
+public:
+   JanitorInitializer();
+private:
+   static int ref_count;
+};
+
+static JanitorInitializer JanInit;
+
+#endif                                // end of SimulateExceptions
+
+#ifdef UseExceptions
+
+#define Try try
+#define Throw(E) throw E
+#define ReThrow throw
+#define Catch catch
+#define CatchAll catch(...)
+#define CatchAndThrow {}
+
+#endif                                // end of UseExceptions
+
+
+#ifdef DisableExceptions              // Disable exceptions
+
+#define Try {
+#define ReThrow Throw()
+#define Catch(EXCEPTION) } if (false) {
+#define CatchAll } if (false)
+#define CatchAndThrow }
+
+inline void Throw() { Terminate(); }
+inline void Throw(const BaseException&) { Terminate(); }
+
+
+#endif                                // end of DisableExceptions
+
+#ifndef SimulateExceptions            // ! SimulateExceptions
+
+class Janitor                         // a dummy version
+{
+public:
+   virtual void CleanUp() {}
+   Janitor() {}
+   virtual ~Janitor() {}
+};
+
+#endif                                // end of ! SimulateExceptions
+
+
+//******************** FREE_CHECK and NEW_DELETE ***********************//
+
+#ifdef DO_FREE_CHECK                          // DO_FREE_CHECK
+// Routines for tracing whether new and delete calls are balanced
+
+class FreeCheck;
+
+class FreeCheckLink
+{
+protected:
+   FreeCheckLink* next;
+   void* ClassStore;
+   FreeCheckLink();
+   virtual void Report()=0;                   // print details of link
+   friend class FreeCheck;
+};
+
+class FCLClass : public FreeCheckLink         // for registering objects
+{
+   char* ClassName;
+   FCLClass(void* t, char* name);
+   void Report();
+   friend class FreeCheck;
+};
+
+class FCLRealArray : public FreeCheckLink     // for registering real arrays
+{
+   char* Operation;
+   int size;
+   FCLRealArray(void* t, char* o, int s);
+   void Report();
+   friend class FreeCheck;
+};
+
+class FCLIntArray : public FreeCheckLink     // for registering int arrays
+{
+   char* Operation;
+   int size;
+   FCLIntArray(void* t, char* o, int s);
+   void Report();
+   friend class FreeCheck;
+};
+
+
+class FreeCheck
+{
+   static FreeCheckLink* next;
+   static int BadDelete;
+public:
+   static void Register(void*, char*);
+   static void DeRegister(void*, char*);
+   static void RegisterR(void*, char*, int);
+   static void DeRegisterR(void*, char*, int);
+   static void RegisterI(void*, char*, int);
+   static void DeRegisterI(void*, char*, int);
+   static void Status();
+   friend class FreeCheckLink;
+   friend class FCLClass;
+   friend class FCLRealArray;
+   friend class FCLIntArray;
+};
+
+#define FREE_CHECK(Class)                                                  \
+public:                                                                    \
+   void* operator new(size_t size)                                         \
+   {                                                                       \
+      void* t = ::operator new(size); FreeCheck::Register(t,#Class);       \
+      return t;                                                            \
+   }                                                                       \
+   void operator delete(void* t)                                           \
+   { FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
+
+
+#ifdef SimulateExceptions         // SimulateExceptions
+
+#define NEW_DELETE(Class)                                                  \
+public:                                                                    \
+   void* operator new(size_t size)                                         \
+   {                                                                       \
+      do_not_link=true;                                                    \
+      void* t = ::operator new(size); FreeCheck::Register(t,#Class);       \
+      return t;                                                            \
+   }                                                                       \
+   void operator delete(void* t)                                           \
+   { FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
+
+
+#endif                           // end of SimulateExceptions
+
+
+#define MONITOR_REAL_NEW(Operation, Size, Pointer)                         \
+	FreeCheck::RegisterR(Pointer, Operation, Size);
+#define MONITOR_INT_NEW(Operation, Size, Pointer)                          \
+	FreeCheck::RegisterI(Pointer, Operation, Size);
+#define MONITOR_REAL_DELETE(Operation, Size, Pointer)                      \
+	FreeCheck::DeRegisterR(Pointer, Operation, Size);
+#define MONITOR_INT_DELETE(Operation, Size, Pointer)                       \
+	FreeCheck::DeRegisterI(Pointer, Operation, Size);
+
+#else                            // DO_FREE_CHECK not defined
+
+#define FREE_CHECK(Class) public:
+#define MONITOR_REAL_NEW(Operation, Size, Pointer) {}
+#define MONITOR_INT_NEW(Operation, Size, Pointer) {}
+#define MONITOR_REAL_DELETE(Operation, Size, Pointer) {}
+#define MONITOR_INT_DELETE(Operation, Size, Pointer) {}
+
+
+#ifdef SimulateExceptions         // SimulateExceptions
+
+
+#define NEW_DELETE(Class)                                                  \
+public:                                                                    \
+	void* operator new(size_t size)                                    \
+	{ do_not_link=true; void* t = ::operator new(size); return t; }    \
+	void operator delete(void* t) { ::operator delete(t); }
+
+#endif                            // end of SimulateExceptions
+
+#endif                            // end of ! DO_FREE_CHECK
+
+#ifndef SimulateExceptions        // ! SimulateExceptions
+
+#define NEW_DELETE(Class) FREE_CHECK(Class)
+
+#endif                            // end of ! SimulateExceptions
+
+
+//********************* derived exceptions ******************************//
+
+class Logic_error : public BaseException
+{
+public:
+   static unsigned long Select;
+   Logic_error(const char* a_what = 0);
+};
+
+class Runtime_error : public BaseException
+{
+public:
+   static unsigned long Select;
+   Runtime_error(const char* a_what = 0);
+};
+
+class Domain_error : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Domain_error(const char* a_what = 0);
+};
+
+class Invalid_argument : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Invalid_argument(const char* a_what = 0);
+};
+
+class Length_error : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Length_error(const char* a_what = 0);
+};
+
+class Out_of_range : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Out_of_range(const char* a_what = 0);
+};
+
+//class Bad_cast : public Logic_error
+//{
+//public:
+//   static unsigned long Select;
+//   Bad_cast(const char* a_what = 0);
+//};
+
+//class Bad_typeid : public Logic_error
+//{
+//public:
+//   static unsigned long Select;
+//   Bad_typeid(const char* a_what = 0);
+//};
+
+class Range_error : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   Range_error(const char* a_what = 0);
+};
+
+class Overflow_error : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   Overflow_error(const char* a_what = 0);
+};
+
+class Bad_alloc : public BaseException
+{
+public:
+   static unsigned long Select;
+   Bad_alloc(const char* a_what = 0);
+};
+
+#ifdef use_namespace
+}
+#endif
+
+
+#endif                            // end of EXCEPTION_LIB
+
+
+// body file: myexcept.cpp
+
+
+
Index: Shared/newmat/newfft.cpp
===================================================================
RCS file: Shared/newmat/newfft.cpp
diff -N Shared/newmat/newfft.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newfft.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,1059 @@
+//$ newfft.cpp
+
+// This is originally by Sande and Gentleman in 1967! I have translated from
+// Fortran into C and a little bit of C++.
+
+// It takes about twice as long as fftw
+// (http://theory.lcs.mit.edu/~fftw/homepage.html)
+// but is much shorter than fftw  and so despite its age
+// might represent a reasonable
+// compromise between speed and complexity.
+// If you really need the speed get fftw.
+
+
+//    THIS SUBROUTINE WAS WRITTEN BY G.SANDE OF PRINCETON UNIVERSITY AND
+//    W.M.GENTLMAN OF THE BELL TELEPHONE LAB.  IT WAS BROUGHT TO LONDON
+//    BY DR. M.D. GODFREY AT THE IMPERIAL COLLEGE AND WAS ADAPTED FOR
+//    BURROUGHS 6700 BY D. R. BRILLINGER AND J. PEMBERTON
+//    IT REPRESENTS THE STATE OF THE ART OF COMPUTING COMPLETE FINITE
+//    DISCRETE FOURIER TRANSFORMS AS OF NOV.1967.
+//    OTHER PROGRAMS REQUIRED.
+//                                 ONLY THOSE SUBROUTINES INCLUDED HERE.
+//                      USAGE.
+//       CALL AR1DFT(N,X,Y)
+//            WHERE  N IS THE NUMBER OF POINTS IN THE SEQUENCE .
+//                   X - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE REAL
+//                       PART OF THE SEQUENCE.
+//                   Y - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE
+//                       IMAGINARY PART OF THE SEQUENCE.
+//    THE TRANSFORM IS RETURNED IN X AND Y.
+//            METHOD
+//               FOR A GENERAL DISCUSSION OF THESE TRANSFORMS AND OF
+//    THE FAST METHOD FOR COMPUTING THEM, SEE GENTLEMAN AND SANDE,
+//    @FAST FOURIER TRANSFORMS - FOR FUN AND PROFIT,@ 1966 FALL JOINT
+//    COMPUTER CONFERENCE.
+//    THIS PROGRAM COMPUTES THIS FOR A COMPLEX SEQUENCE Z(T) OF LENGTH
+//    N WHOSE ELEMENTS ARE STORED AT(X(I) , Y(I)) AND RETURNS THE
+//    TRANSFORM COEFFICIENTS AT (X(I), Y(I)).
+//        DESCRIPTION
+//    AR1DFT IS A HIGHLY MODULAR ROUTINE CAPABLE OF COMPUTING IN PLACE
+//    THE COMPLETE FINITE DISCRETE FOURIER TRANSFORM  OF A ONE-
+//    DIMENSIONAL SEQUENCE OF RATHER GENERAL LENGTH N.
+//       THE MAIN ROUTINE , AR1DFT ITSELF, FACTORS N. IT THEN CALLS ON
+//    ON GR 1D FT TO COMPUTE THE ACTUAL TRANSFORMS, USING THESE FACTORS.
+//    THIS GR 1D FT DOES, CALLING AT EACH STAGE ON THE APPROPRIATE KERN
+//    EL R2FTK, R4FTK, R8FTK, R16FTK, R3FTK, R5FTK, OR RPFTK TO PERFORM
+//    THE COMPUTATIONS FOR THIS PASS OVER THE SEQUENCE, DEPENDING ON
+//    WHETHER THE CORRESPONDING FACTOR IS 2, 4, 8, 16, 3, 5, OR SOME
+//    MORE GENERAL PRIME P. WHEN GR1DFT IS FINISHED THE TRANSFORM IS
+//    COMPUTED, HOWEVER, THE RESULTS ARE STORED IN "DIGITS REVERSED"
+//    ORDER. AR1DFT THEREFORE, CALLS UPON GR 1S FS TO SORT THEM OUT.
+//    TO RETURN TO THE FACTORIZATION, SINGLETON HAS POINTED OUT THAT
+//    THE TRANSFORMS ARE MORE EFFICIENT IF THE SAMPLE SIZE N, IS OF THE
+//    FORM B*A**2 AND B CONSISTS OF A SINGLE FACTOR.  IN SUCH A CASE
+//    IF WE PROCESS THE FACTORS IN THE ORDER ABA  THEN
+//    THE REORDERING CAN BE DONE AS FAST IN PLACE, AS WITH SCRATCH
+//    STORAGE.  BUT AS B BECOMES MORE COMPLICATED, THE COST OF THE DIGIT
+//    REVERSING DUE TO B PART BECOMES VERY EXPENSIVE IF WE TRY TO DO IT
+//    IN PLACE.  IN SUCH A CASE IT MIGHT BE BETTER TO USE EXTRA STORAGE
+//    A ROUTINE TO DO THIS IS, HOWEVER, NOT INCLUDED HERE.
+//    ANOTHER FEATURE INFLUENCING THE FACTORIZATION IS THAT FOR ANY FIXED
+//    FACTOR N WE CAN PREPARE A SPECIAL KERNEL WHICH WILL COMPUTE
+//    THAT STAGE OF THE TRANSFORM MORE EFFICIENTLY THAN WOULD A KERNEL
+//    FOR GENERAL FACTORS, ESPECIALLY IF THE GENERAL KERNEL HAD TO BE
+//    APPLIED SEVERAL TIMES. FOR EXAMPLE, FACTORS OF 4 ARE MORE
+//    EFFICIENT THAN FACTORS OF 2, FACTORS OF 8 MORE EFFICIENT THAN 4,ETC
+//    ON THE OTHER HAND DIMINISHING RETURNS RAPIDLY SET IN, ESPECIALLY
+//    SINCE THE LENGTH OF THE KERNEL FOR A SPECIAL CASE IS ROUGHLY
+//    PROPORTIONAL TO THE FACTOR IT DEALS WITH. HENCE THESE PROBABLY ARE
+//    ALL THE KERNELS WE WISH TO HAVE.
+//            RESTRICTIONS.
+//    AN UNFORTUNATE FEATURE OF THE SORTING PROBLEM IS THAT THE MOST
+//    EFFICIENT WAY TO DO IT IS WITH NESTED DO LOOPS, ONE FOR EACH
+//    FACTOR. THIS PUTS A RESTRICTION ON N AS TO HOW MANY FACTORS IT
+//    CAN HAVE.  CURRENTLY THE LIMIT IS 16, BUT THE LIMIT CAN BE READILY
+//    RAISED IF NECESSARY.
+//    A SECOND RESTRICTION OF THE PROGRAM IS THAT LOCAL STORAGE OF THE
+//    THE ORDER P**2 IS REQUIRED BY THE GENERAL KERNEL RPFTK, SO SOME
+//    LIMIT MUST BE SET ON P.  CURRENTLY THIS IS 19, BUT IT CAN BE INCRE
+//    INCREASED BY TRIVIAL CHANGES.
+//       OTHER COMMENTS.
+//(1) THE ROUTINE IS ADAPTED TO CHECK WHETHER A GIVEN N WILL MEET THE
+//    ABOVE FACTORING REQUIREMENTS AN, IF NOT, TO RETURN THE NEXT HIGHER
+//    NUMBER, NX, SAY, WHICH WILL MEET THESE REQUIREMENTS.
+//    THIS CAN BE ACCHIEVED BY   A STATEMENT OF THE FORM
+//            CALL FACTR(N,X,Y).
+//    IF A DIFFERENT N, SAY NX, IS RETURNED THEN THE TRANSFORMS COULD BE
+//    OBTAINED BY EXTENDING THE SIZE OF THE X-ARRAY AND Y-ARRAY TO NX,
+//    AND SETTING X(I) = Y(I) = 0., FOR I = N+1, NX.
+//(2) IF THE SEQUENCE Z IS ONLY A REAL SEQUENCE, THEN THE IMAGINARY PART
+//    Y(I)=0., THIS WILL RETURN THE COSINE TRANSFORM OF THE REAL SEQUENCE
+//    IN X, AND THE SINE TRANSFORM IN Y.
+
+
+#define WANT_STREAM
+
+#define WANT_MATH
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,20); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+inline Real square(Real x) { return x*x; }
+inline int square(int x) { return x*x; }
+
+static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM,
+   const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM,
+   Real* X, Real* Y);
+static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR,
+   Real* X, Real* Y);
+static void R_P_FTK (int N, int M, int P, Real* X, Real* Y);
+static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1);
+static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2);
+static void R_4_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3);
+static void R_5_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2,
+   Real* X3, Real* Y3, Real* X4, Real* Y4);
+static void R_8_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7);
+static void R_16_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7,
+   Real* X8, Real* Y8, Real* X9, Real* Y9,
+   Real* X10, Real* Y10, Real* X11, Real* Y11,
+   Real* X12, Real* Y12, Real* X13, Real* Y13,
+   Real* X14, Real* Y14, Real* X15, Real* Y15);
+static int BitReverse(int x, int prod, int n, const SimpleIntArray& f);
+
+
+bool FFT_Controller::ar_1d_ft (int PTS, Real* X, Real *Y)
+{
+//    ARBITRARY RADIX ONE DIMENSIONAL FOURIER TRANSFORM
+
+   REPORT
+
+   int  F,J,N,NF,P,PMAX,P_SYM,P_TWO,Q,R,TWO_GRP;
+
+   // NP is maximum number of squared factors allows PTS up to 2**32 at least
+   // NQ is number of not-squared factors - increase if we increase PMAX
+   const int NP = 16, NQ = 10;
+   SimpleIntArray PP(NP), QQ(NQ);
+
+   TWO_GRP=16; PMAX=19;
+
+   // PMAX is the maximum factor size
+   // TWO_GRP is the maximum power of 2 handled as a single factor
+   // Doesn't take advantage of combining powers of 2 when calculating
+   // number of factors
+
+   if (PTS<=1) return true;
+   N=PTS; P_SYM=1; F=2; P=0; Q=0;
+
+   // P counts the number of squared factors
+   // Q counts the number of the rest
+   // R = 0 for no non-squared factors; 1 otherwise
+
+   // FACTOR holds all the factors - non-squared ones in the middle
+   //   - length is 2*P+Q
+   // SYM also holds all the factors but with the non-squared ones
+   //   multiplied together - length is 2*P+R
+   // PP holds the values of the squared factors - length is P
+   // QQ holds the values of the rest - length is Q
+
+   // P_SYM holds the product of the squared factors
+
+   // find the factors - load into PP and QQ
+   while (N > 1)
+   {
+      bool fail = true;
+      for (J=F; J<=PMAX; J++)
+         if (N % J == 0) { fail = false; F=J; break; }
+      if (fail || P >= NP || Q >= NQ) return false; // can't factor
+      N /= F;
+      if (N % F != 0) QQ[Q++] = F;
+      else { N /= F; PP[P++] = F; P_SYM *= F; }
+   }
+
+   R = (Q == 0) ? 0 : 1;  // R = 0 if no not-squared factors, 1 otherwise
+
+   NF = 2*P + Q;
+   SimpleIntArray FACTOR(NF + 1), SYM(2*P + R);
+   FACTOR[NF] = 0;                // we need this in the "combine powers of 2"
+
+   // load into SYM and FACTOR
+   for (J=0; J<P; J++)
+      { SYM[J]=FACTOR[J]=PP[P-1-J]; FACTOR[P+Q+J]=SYM[P+R+J]=PP[J]; }
+
+   if (Q>0)
+   {
+      REPORT
+      for (J=0; J<Q; J++) FACTOR[P+J]=QQ[J];
+      SYM[P]=PTS/square(P_SYM);
+   }
+
+   // combine powers of 2
+   P_TWO = 1;
+   for (J=0; J < NF; J++)
+   {
+      if (FACTOR[J]!=2) continue;
+      P_TWO=P_TWO*2; FACTOR[J]=1;
+      if (P_TWO<TWO_GRP && FACTOR[J+1]==2) continue;
+      FACTOR[J]=P_TWO; P_TWO=1;
+   }
+
+   if (P==0) R=0;
+   if (Q<=1) Q=0;
+
+   // do the analysis
+   GR_1D_FT(PTS,NF,FACTOR,X,Y);                 // the transform
+   GR_1D_FS(PTS,2*P+R,Q,SYM,P_SYM,QQ,X,Y);      // the reshuffling
+
+   return true;
+
+}
+
+static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM,
+   const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM,
+   Real* X, Real* Y)
+{
+//    GENERAL RADIX ONE DIMENSIONAL FOURIER SORT
+
+// PTS = number of points
+// N_SYM = length of SYM
+// N_UN_SYM = length of UN_SYM
+// SYM: squared factors + product of non-squared factors + squared factors
+// P_SYM = product of squared factors (each included only once)
+// UN_SYM: not-squared factors
+
+   REPORT
+
+   Real T;
+   int  JJ,KK,P_UN_SYM;
+
+   // I have replaced the multiple for-loop used by Sande-Gentleman code
+   // by the following code which does not limit the number of factors
+
+   if (N_SYM > 0)
+   {
+      REPORT
+      SimpleIntArray U(N_SYM);
+      for(MultiRadixCounter MRC(N_SYM, SYM, U); !MRC.Finish(); ++MRC)
+      {
+         if (MRC.Swap())
+         {
+            int P = MRC.Reverse(); int JJ = MRC.Counter(); Real T;
+            T=X[JJ]; X[JJ]=X[P]; X[P]=T; T=Y[JJ]; Y[JJ]=Y[P]; Y[P]=T;
+         }
+      }
+   }
+
+   int J,JL,K,L,M,MS;
+
+   // UN_SYM contains the non-squared factors
+   // I have replaced the Sande-Gentleman code as it runs into
+   // integer overflow problems
+   // My code (and theirs) would be improved by using a bit array
+   // as suggested by Van Loan
+
+   if (N_UN_SYM==0) { REPORT return; }
+   P_UN_SYM=PTS/square(P_SYM); JL=(P_UN_SYM-3)*P_SYM; MS=P_UN_SYM*P_SYM;
+
+   for (J = P_SYM; J<=JL; J+=P_SYM)
+   {
+      K=J;
+      do K = P_SYM * BitReverse(K / P_SYM, P_UN_SYM, N_UN_SYM, UN_SYM);
+      while (K<J);
+
+      if (K!=J)
+      {
+         REPORT
+         for (L=0; L<P_SYM; L++) for (M=L; M<PTS; M+=MS)
+         {
+            JJ=M+J; KK=M+K;
+            T=X[JJ]; X[JJ]=X[KK]; X[KK]=T; T=Y[JJ]; Y[JJ]=Y[KK]; Y[KK]=T;
+         }
+      }
+   }
+
+   return;
+}
+
+static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR,
+   Real* X, Real* Y)
+{
+//    GENERAL RADIX ONE DIMENSIONAL FOURIER TRANSFORM;
+
+   REPORT
+
+   int  M = N;
+
+   for (int i = 0; i < N_FACTOR; i++)
+   {
+      int P = FACTOR[i]; M /= P;
+
+      switch(P)
+      {
+      case 1: REPORT break;
+      case 2: REPORT R_2_FTK (N,M,X,Y,X+M,Y+M); break;
+      case 3: REPORT R_3_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M); break;
+      case 4: REPORT R_4_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M); break;
+      case 5:
+         REPORT
+         R_5_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M,X+4*M,Y+4*M);
+         break;
+      case 8:
+         REPORT
+         R_8_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,
+            X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M,
+            X+6*M,Y+6*M,X+7*M,Y+7*M);
+         break;
+      case 16:
+         REPORT
+         R_16_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,
+            X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M,
+            X+6*M,Y+6*M,X+7*M,Y+7*M,X+8*M,Y+8*M,
+            X+9*M,Y+9*M,X+10*M,Y+10*M,X+11*M,Y+11*M,
+            X+12*M,Y+12*M,X+13*M,Y+13*M,X+14*M,Y+14*M,
+            X+15*M,Y+15*M);
+         break;
+      default: REPORT R_P_FTK (N,M,P,X,Y); break;
+      }
+   }
+
+}
+
+static void R_P_FTK (int N, int M, int P, Real* X, Real* Y)
+//    RADIX PRIME FOURIER TRANSFORM KERNEL;
+// X and Y are treated as M * P matrices with Fortran storage
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   Real ANGLE,IS,IU,RS,RU,T,TWOPI,XT,YT;
+   int  J,JJ,K0,K,M_OVER_2,MP,PM,PP,U,V;
+
+   Real AA [9][9], BB [9][9];
+   Real A [18], B [18], C [18], S [18];
+   Real IA [9], IB [9], RA [9], RB [9];
+
+   TWOPI=8.0*atan(1.0);
+   M_OVER_2=M/2+1; MP=M*P; PP=P/2; PM=P-1;
+
+   for (U=0; U<PP; U++)
+   {
+      ANGLE=TWOPI*Real(U+1)/Real(P);
+      JJ=P-U-2;
+      A[U]=cos(ANGLE); B[U]=sin(ANGLE);
+      A[JJ]=A[U]; B[JJ]= -B[U];
+   }
+
+   for (U=1; U<=PP; U++)
+   {
+      for (V=1; V<=PP; V++)
+         { JJ=U*V-U*V/P*P; AA[V-1][U-1]=A[JJ-1]; BB[V-1][U-1]=B[JJ-1]; }
+   }
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(MP); ZERO=ANGLE==0.0;
+      C[0]=cos(ANGLE); S[0]=sin(ANGLE);
+      for (U=1; U<PM; U++)
+      {
+         C[U]=C[U-1]*C[0]-S[U-1]*S[0];
+         S[U]=S[U-1]*C[0]+C[U-1]*S[0];
+      }
+      goto L700;
+   L500:
+      REPORT
+      if (NO_FOLD) { REPORT goto L1500; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      for (U=0; U<PM; U++)
+         { T=C[U]*A[U]+S[U]*B[U]; S[U]= -S[U]*A[U]+C[U]*B[U]; C[U]=T; }
+   L700:
+      REPORT
+      for (K=K0; K<N; K+=MP)
+      {
+         XT=X[K]; YT=Y[K];
+         for (U=1; U<=PP; U++)
+         {
+            RA[U-1]=XT; IA[U-1]=YT;
+            RB[U-1]=0.0; IB[U-1]=0.0;
+         }
+         for (U=1; U<=PP; U++)
+         {
+            JJ=P-U;
+            RS=X[K+M*U]+X[K+M*JJ]; IS=Y[K+M*U]+Y[K+M*JJ];
+            RU=X[K+M*U]-X[K+M*JJ]; IU=Y[K+M*U]-Y[K+M*JJ];
+            XT=XT+RS; YT=YT+IS;
+            for (V=0; V<PP; V++)
+            {
+               RA[V]=RA[V]+RS*AA[V][U-1]; IA[V]=IA[V]+IS*AA[V][U-1];
+               RB[V]=RB[V]+RU*BB[V][U-1]; IB[V]=IB[V]+IU*BB[V][U-1];
+            }
+         }
+         X[K]=XT; Y[K]=YT;
+         for (U=1; U<=PP; U++)
+         {
+            if (!ZERO)
+            {
+               REPORT
+               XT=RA[U-1]+IB[U-1]; YT=IA[U-1]-RB[U-1];
+               X[K+M*U]=XT*C[U-1]+YT*S[U-1]; Y[K+M*U]=YT*C[U-1]-XT*S[U-1];
+               JJ=P-U;
+               XT=RA[U-1]-IB[U-1]; YT=IA[U-1]+RB[U-1];
+               X[K+M*JJ]=XT*C[JJ-1]+YT*S[JJ-1];
+               Y[K+M*JJ]=YT*C[JJ-1]-XT*S[JJ-1];
+            }
+            else
+            {
+               REPORT
+               X[K+M*U]=RA[U-1]+IB[U-1]; Y[K+M*U]=IA[U-1]-RB[U-1];
+               JJ=P-U;
+               X[K+M*JJ]=RA[U-1]-IB[U-1]; Y[K+M*JJ]=IA[U-1]+RB[U-1];
+            }
+         }
+      }
+      goto L500;
+L1500: ;
+   }
+   return;
+}
+
+static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1)
+//    RADIX TWO FOURIER TRANSFORM KERNEL;
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M2,M_OVER_2;
+   Real ANGLE,C,IS,IU,RS,RU,S,TWOPI;
+
+   M2=M*2; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M2); ZERO=ANGLE==0.0;
+      C=cos(ANGLE); S=sin(ANGLE);
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J; C= -C;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M2)
+      {
+         RS=X0[K]+X1[K]; IS=Y0[K]+Y1[K];
+         RU=X0[K]-X1[K]; IU=Y0[K]-Y1[K];
+         X0[K]=RS; Y0[K]=IS;
+         if (!ZERO) { X1[K]=RU*C+IU*S; Y1[K]=IU*C-RU*S; }
+         else { X1[K]=RU; Y1[K]=IU; }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2)
+//    RADIX THREE FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M3,M_OVER_2;
+   Real ANGLE,A,B,C1,C2,S1,S2,T,TWOPI;
+   Real I0,I1,I2,IA,IB,IS,R0,R1,R2,RA,RB,RS;
+
+   M3=M*3; M_OVER_2=M/2+1; TWOPI=8.0*atan(1.0);
+   A=cos(TWOPI/3.0); B=sin(TWOPI/3.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M3); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*A+S1*B; S1=C1*B-S1*A; C1=T;
+      T=C2*A-S2*B; S2= -C2*B-S2*A; C2=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M3)
+      {
+         R0 = X0[K]; I0 = Y0[K];
+         RS=X1[K]+X2[K]; IS=Y1[K]+Y2[K];
+         X0[K]=R0+RS; Y0[K]=I0+IS;
+         RA=R0+RS*A; IA=I0+IS*A;
+         RB=(X1[K]-X2[K])*B; IB=(Y1[K]-Y2[K])*B;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RA+IB; I1=IA-RB; R2=RA-IB; I2=IA+RB;
+            X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+         }
+         else { REPORT X1[K]=RA+IB; Y1[K]=IA-RB; X2[K]=RA-IB; Y2[K]=IA+RB; }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_4_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3)
+//    RADIX FOUR FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M4,M_OVER_2;
+   Real ANGLE,C1,C2,C3,S1,S2,S3,T,TWOPI;
+   Real I1,I2,I3,IS0,IS1,IU0,IU1,R1,R2,R3,RS0,RS1,RU0,RU1;
+
+   M4=M*4; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M4); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1; C1=S1; S1=T;
+      C2= -C2;
+      T=C3; C3= -S3; S3= -T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M4)
+      {
+         RS0=X0[K]+X2[K]; IS0=Y0[K]+Y2[K];
+         RU0=X0[K]-X2[K]; IU0=Y0[K]-Y2[K];
+         RS1=X1[K]+X3[K]; IS1=Y1[K]+Y3[K];
+         RU1=X1[K]-X3[K]; IU1=Y1[K]-Y3[K];
+         X0[K]=RS0+RS1; Y0[K]=IS0+IS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RU0+IU1; I1=IU0-RU1;
+            R2=RS0-RS1; I2=IS0-IS1;
+            R3=RU0-IU1; I3=IU0+RU1;
+            X2[K]=R1*C1+I1*S1; Y2[K]=I1*C1-R1*S1;
+            X1[K]=R2*C2+I2*S2; Y1[K]=I2*C2-R2*S2;
+            X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3;
+         }
+         else
+         {
+            REPORT
+            X2[K]=RU0+IU1; Y2[K]=IU0-RU1;
+            X1[K]=RS0-RS1; Y1[K]=IS0-IS1;
+            X3[K]=RU0-IU1; Y3[K]=IU0+RU1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_5_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2,
+   Real* X3, Real* Y3, Real* X4, Real* Y4)
+//    RADIX FIVE FOURIER TRANSFORM KERNEL
+
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M5,M_OVER_2;
+   Real ANGLE,A1,A2,B1,B2,C1,C2,C3,C4,S1,S2,S3,S4,T,TWOPI;
+   Real R0,R1,R2,R3,R4,RA1,RA2,RB1,RB2,RS1,RS2,RU1,RU2;
+   Real I0,I1,I2,I3,I4,IA1,IA2,IB1,IB2,IS1,IS2,IU1,IU2;
+
+   M5=M*5; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+   A1=cos(TWOPI/5.0); B1=sin(TWOPI/5.0);
+   A2=cos(2.0*TWOPI/5.0); B2=sin(2.0*TWOPI/5.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M5); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*A1+S1*B1; S1=C1*B1-S1*A1; C1=T;
+      T=C2*A2+S2*B2; S2=C2*B2-S2*A2; C2=T;
+      T=C3*A2-S3*B2; S3= -C3*B2-S3*A2; C3=T;
+      T=C4*A1-S4*B1; S4= -C4*B1-S4*A1; C4=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M5)
+      {
+         R0=X0[K]; I0=Y0[K];
+         RS1=X1[K]+X4[K]; IS1=Y1[K]+Y4[K];
+         RU1=X1[K]-X4[K]; IU1=Y1[K]-Y4[K];
+         RS2=X2[K]+X3[K]; IS2=Y2[K]+Y3[K];
+         RU2=X2[K]-X3[K]; IU2=Y2[K]-Y3[K];
+         X0[K]=R0+RS1+RS2; Y0[K]=I0+IS1+IS2;
+         RA1=R0+RS1*A1+RS2*A2; IA1=I0+IS1*A1+IS2*A2;
+         RA2=R0+RS1*A2+RS2*A1; IA2=I0+IS1*A2+IS2*A1;
+         RB1=RU1*B1+RU2*B2; IB1=IU1*B1+IU2*B2;
+         RB2=RU1*B2-RU2*B1; IB2=IU1*B2-IU2*B1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RA1+IB1; I1=IA1-RB1;
+            R2=RA2+IB2; I2=IA2-RB2;
+            R3=RA2-IB2; I3=IA2+RB2;
+            R4=RA1-IB1; I4=IA1+RB1;
+            X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+            X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3;
+            X4[K]=R4*C4+I4*S4; Y4[K]=I4*C4-R4*S4;
+         }
+         else
+         {
+            REPORT
+            X1[K]=RA1+IB1; Y1[K]=IA1-RB1;
+            X2[K]=RA2+IB2; Y2[K]=IA2-RB2;
+            X3[K]=RA2-IB2; Y3[K]=IA2+RB2;
+            X4[K]=RA1-IB1; Y4[K]=IA1+RB1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_8_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7)
+//    RADIX EIGHT FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M8,M_OVER_2;
+   Real ANGLE,C1,C2,C3,C4,C5,C6,C7,E,S1,S2,S3,S4,S5,S6,S7,T,TWOPI;
+   Real R1,R2,R3,R4,R5,R6,R7,RS0,RS1,RS2,RS3,RU0,RU1,RU2,RU3;
+   Real I1,I2,I3,I4,I5,I6,I7,IS0,IS1,IS2,IS3,IU0,IU1,IU2,IU3;
+   Real RSS0,RSS1,RSU0,RSU1,RUS0,RUS1,RUU0,RUU1;
+   Real ISS0,ISS1,ISU0,ISU1,IUS0,IUS1,IUU0,IUU1;
+
+   M8=M*8; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0); E=cos(TWOPI/8.0);
+
+   for (J=0;J<M_OVER_2;J++)
+   {
+      NO_FOLD= (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M8); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=C1*S1+S1*C1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      C5=C4*C1-S4*S1; S5=S4*C1+C4*S1;
+      C6=C4*C2-S4*S2; S6=S4*C2+C4*S2;
+      C7=C4*C3-S4*S3; S7=S4*C3+C4*S3;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=(C1+S1)*E; S1=(C1-S1)*E; C1=T;
+      T=S2; S2=C2; C2=T;
+      T=(-C3+S3)*E; S3=(C3+S3)*E; C3=T;
+      C4= -C4;
+      T= -(C5+S5)*E; S5=(-C5+S5)*E; C5=T;
+      T= -S6; S6= -C6; C6=T;
+      T=(C7-S7)*E; S7= -(C7+S7)*E; C7=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M8)
+      {
+         RS0=X0[K]+X4[K]; IS0=Y0[K]+Y4[K];
+         RU0=X0[K]-X4[K]; IU0=Y0[K]-Y4[K];
+         RS1=X1[K]+X5[K]; IS1=Y1[K]+Y5[K];
+         RU1=X1[K]-X5[K]; IU1=Y1[K]-Y5[K];
+         RS2=X2[K]+X6[K]; IS2=Y2[K]+Y6[K];
+         RU2=X2[K]-X6[K]; IU2=Y2[K]-Y6[K];
+         RS3=X3[K]+X7[K]; IS3=Y3[K]+Y7[K];
+         RU3=X3[K]-X7[K]; IU3=Y3[K]-Y7[K];
+         RSS0=RS0+RS2; ISS0=IS0+IS2;
+         RSU0=RS0-RS2; ISU0=IS0-IS2;
+         RSS1=RS1+RS3; ISS1=IS1+IS3;
+         RSU1=RS1-RS3; ISU1=IS1-IS3;
+         RUS0=RU0-IU2; IUS0=IU0+RU2;
+         RUU0=RU0+IU2; IUU0=IU0-RU2;
+         RUS1=RU1-IU3; IUS1=IU1+RU3;
+         RUU1=RU1+IU3; IUU1=IU1-RU3;
+         T=(RUS1+IUS1)*E; IUS1=(IUS1-RUS1)*E; RUS1=T;
+         T=(RUU1+IUU1)*E; IUU1=(IUU1-RUU1)*E; RUU1=T;
+         X0[K]=RSS0+RSS1; Y0[K]=ISS0+ISS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RUU0+RUU1; I1=IUU0+IUU1;
+            R2=RSU0+ISU1; I2=ISU0-RSU1;
+            R3=RUS0+IUS1; I3=IUS0-RUS1;
+            R4=RSS0-RSS1; I4=ISS0-ISS1;
+            R5=RUU0-RUU1; I5=IUU0-IUU1;
+            R6=RSU0-ISU1; I6=ISU0+RSU1;
+            R7=RUS0-IUS1; I7=IUS0+RUS1;
+            X4[K]=R1*C1+I1*S1; Y4[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+            X6[K]=R3*C3+I3*S3; Y6[K]=I3*C3-R3*S3;
+            X1[K]=R4*C4+I4*S4; Y1[K]=I4*C4-R4*S4;
+            X5[K]=R5*C5+I5*S5; Y5[K]=I5*C5-R5*S5;
+            X3[K]=R6*C6+I6*S6; Y3[K]=I6*C6-R6*S6;
+            X7[K]=R7*C7+I7*S7; Y7[K]=I7*C7-R7*S7;
+         }
+         else
+         {
+            REPORT
+            X4[K]=RUU0+RUU1; Y4[K]=IUU0+IUU1;
+            X2[K]=RSU0+ISU1; Y2[K]=ISU0-RSU1;
+            X6[K]=RUS0+IUS1; Y6[K]=IUS0-RUS1;
+            X1[K]=RSS0-RSS1; Y1[K]=ISS0-ISS1;
+            X5[K]=RUU0-RUU1; Y5[K]=IUU0-IUU1;
+            X3[K]=RSU0-ISU1; Y3[K]=ISU0+RSU1;
+            X7[K]=RUS0-IUS1; Y7[K]=IUS0+RUS1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_16_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7,
+   Real* X8, Real* Y8, Real* X9, Real* Y9,
+   Real* X10, Real* Y10, Real* X11, Real* Y11,
+   Real* X12, Real* Y12, Real* X13, Real* Y13,
+   Real* X14, Real* Y14, Real* X15, Real* Y15)
+//    RADIX SIXTEEN FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M16,M_OVER_2;
+   Real ANGLE,EI1,ER1,E2,EI3,ER3,EI5,ER5,T,TWOPI;
+   Real RS0,RS1,RS2,RS3,RS4,RS5,RS6,RS7;
+   Real IS0,IS1,IS2,IS3,IS4,IS5,IS6,IS7;
+   Real RU0,RU1,RU2,RU3,RU4,RU5,RU6,RU7;
+   Real IU0,IU1,IU2,IU3,IU4,IU5,IU6,IU7;
+   Real RUS0,RUS1,RUS2,RUS3,RUU0,RUU1,RUU2,RUU3;
+   Real ISS0,ISS1,ISS2,ISS3,ISU0,ISU1,ISU2,ISU3;
+   Real RSS0,RSS1,RSS2,RSS3,RSU0,RSU1,RSU2,RSU3;
+   Real IUS0,IUS1,IUS2,IUS3,IUU0,IUU1,IUU2,IUU3;
+   Real RSSS0,RSSS1,RSSU0,RSSU1,RSUS0,RSUS1,RSUU0,RSUU1;
+   Real ISSS0,ISSS1,ISSU0,ISSU1,ISUS0,ISUS1,ISUU0,ISUU1;
+   Real RUSS0,RUSS1,RUSU0,RUSU1,RUUS0,RUUS1,RUUU0,RUUU1;
+   Real IUSS0,IUSS1,IUSU0,IUSU1,IUUS0,IUUS1,IUUU0,IUUU1;
+   Real R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15;
+   Real I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12,I13,I14,I15;
+   Real C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15;
+   Real S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,S12,S13,S14,S15;
+
+   M16=M*16; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+   ER1=cos(TWOPI/16.0); EI1=sin(TWOPI/16.0);
+   E2=cos(TWOPI/8.0);
+   ER3=cos(3.0*TWOPI/16.0); EI3=sin(3.0*TWOPI/16.0);
+   ER5=cos(5.0*TWOPI/16.0); EI5=sin(5.0*TWOPI/16.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M16);
+      ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=C1*S1+S1*C1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      C5=C4*C1-S4*S1; S5=S4*C1+C4*S1;
+      C6=C4*C2-S4*S2; S6=S4*C2+C4*S2;
+      C7=C4*C3-S4*S3; S7=S4*C3+C4*S3;
+      C8=C4*C4-S4*S4; S8=C4*S4+S4*C4;
+      C9=C8*C1-S8*S1; S9=S8*C1+C8*S1;
+      C10=C8*C2-S8*S2; S10=S8*C2+C8*S2;
+      C11=C8*C3-S8*S3; S11=S8*C3+C8*S3;
+      C12=C8*C4-S8*S4; S12=S8*C4+C8*S4;
+      C13=C8*C5-S8*S5; S13=S8*C5+C8*S5;
+      C14=C8*C6-S8*S6; S14=S8*C6+C8*S6;
+      C15=C8*C7-S8*S7; S15=S8*C7+C8*S7;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*ER1+S1*EI1; S1= -S1*ER1+C1*EI1; C1=T;
+      T=(C2+S2)*E2; S2=(C2-S2)*E2; C2=T;
+      T=C3*ER3+S3*EI3; S3= -S3*ER3+C3*EI3; C3=T;
+      T=S4; S4=C4; C4=T;
+      T=S5*ER1-C5*EI1; S5=C5*ER1+S5*EI1; C5=T;
+      T=(-C6+S6)*E2; S6=(C6+S6)*E2; C6=T;
+      T=S7*ER3-C7*EI3; S7=C7*ER3+S7*EI3; C7=T;
+      C8= -C8;
+      T= -(C9*ER1+S9*EI1); S9=S9*ER1-C9*EI1; C9=T;
+      T= -(C10+S10)*E2; S10=(-C10+S10)*E2; C10=T;
+      T= -(C11*ER3+S11*EI3); S11=S11*ER3-C11*EI3; C11=T;
+      T= -S12; S12= -C12; C12=T;
+      T= -S13*ER1+C13*EI1; S13= -(C13*ER1+S13*EI1); C13=T;
+      T=(C14-S14)*E2; S14= -(C14+S14)*E2; C14=T;
+      T= -S15*ER3+C15*EI3; S15= -(C15*ER3+S15*EI3); C15=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M16)
+      {
+         RS0=X0[K]+X8[K]; IS0=Y0[K]+Y8[K];
+         RU0=X0[K]-X8[K]; IU0=Y0[K]-Y8[K];
+         RS1=X1[K]+X9[K]; IS1=Y1[K]+Y9[K];
+         RU1=X1[K]-X9[K]; IU1=Y1[K]-Y9[K];
+         RS2=X2[K]+X10[K]; IS2=Y2[K]+Y10[K];
+         RU2=X2[K]-X10[K]; IU2=Y2[K]-Y10[K];
+         RS3=X3[K]+X11[K]; IS3=Y3[K]+Y11[K];
+         RU3=X3[K]-X11[K]; IU3=Y3[K]-Y11[K];
+         RS4=X4[K]+X12[K]; IS4=Y4[K]+Y12[K];
+         RU4=X4[K]-X12[K]; IU4=Y4[K]-Y12[K];
+         RS5=X5[K]+X13[K]; IS5=Y5[K]+Y13[K];
+         RU5=X5[K]-X13[K]; IU5=Y5[K]-Y13[K];
+         RS6=X6[K]+X14[K]; IS6=Y6[K]+Y14[K];
+         RU6=X6[K]-X14[K]; IU6=Y6[K]-Y14[K];
+         RS7=X7[K]+X15[K]; IS7=Y7[K]+Y15[K];
+         RU7=X7[K]-X15[K]; IU7=Y7[K]-Y15[K];
+         RSS0=RS0+RS4; ISS0=IS0+IS4;
+         RSS1=RS1+RS5; ISS1=IS1+IS5;
+         RSS2=RS2+RS6; ISS2=IS2+IS6;
+         RSS3=RS3+RS7; ISS3=IS3+IS7;
+         RSU0=RS0-RS4; ISU0=IS0-IS4;
+         RSU1=RS1-RS5; ISU1=IS1-IS5;
+         RSU2=RS2-RS6; ISU2=IS2-IS6;
+         RSU3=RS3-RS7; ISU3=IS3-IS7;
+         RUS0=RU0-IU4; IUS0=IU0+RU4;
+         RUS1=RU1-IU5; IUS1=IU1+RU5;
+         RUS2=RU2-IU6; IUS2=IU2+RU6;
+         RUS3=RU3-IU7; IUS3=IU3+RU7;
+         RUU0=RU0+IU4; IUU0=IU0-RU4;
+         RUU1=RU1+IU5; IUU1=IU1-RU5;
+         RUU2=RU2+IU6; IUU2=IU2-RU6;
+         RUU3=RU3+IU7; IUU3=IU3-RU7;
+         T=(RSU1+ISU1)*E2; ISU1=(ISU1-RSU1)*E2; RSU1=T;
+         T=(RSU3+ISU3)*E2; ISU3=(ISU3-RSU3)*E2; RSU3=T;
+         T=RUS1*ER3+IUS1*EI3; IUS1=IUS1*ER3-RUS1*EI3; RUS1=T;
+         T=(RUS2+IUS2)*E2; IUS2=(IUS2-RUS2)*E2; RUS2=T;
+         T=RUS3*ER5+IUS3*EI5; IUS3=IUS3*ER5-RUS3*EI5; RUS3=T;
+         T=RUU1*ER1+IUU1*EI1; IUU1=IUU1*ER1-RUU1*EI1; RUU1=T;
+         T=(RUU2+IUU2)*E2; IUU2=(IUU2-RUU2)*E2; RUU2=T;
+         T=RUU3*ER3+IUU3*EI3; IUU3=IUU3*ER3-RUU3*EI3; RUU3=T;
+         RSSS0=RSS0+RSS2; ISSS0=ISS0+ISS2;
+         RSSS1=RSS1+RSS3; ISSS1=ISS1+ISS3;
+         RSSU0=RSS0-RSS2; ISSU0=ISS0-ISS2;
+         RSSU1=RSS1-RSS3; ISSU1=ISS1-ISS3;
+         RSUS0=RSU0-ISU2; ISUS0=ISU0+RSU2;
+         RSUS1=RSU1-ISU3; ISUS1=ISU1+RSU3;
+         RSUU0=RSU0+ISU2; ISUU0=ISU0-RSU2;
+         RSUU1=RSU1+ISU3; ISUU1=ISU1-RSU3;
+         RUSS0=RUS0-IUS2; IUSS0=IUS0+RUS2;
+         RUSS1=RUS1-IUS3; IUSS1=IUS1+RUS3;
+         RUSU0=RUS0+IUS2; IUSU0=IUS0-RUS2;
+         RUSU1=RUS1+IUS3; IUSU1=IUS1-RUS3;
+         RUUS0=RUU0+RUU2; IUUS0=IUU0+IUU2;
+         RUUS1=RUU1+RUU3; IUUS1=IUU1+IUU3;
+         RUUU0=RUU0-RUU2; IUUU0=IUU0-IUU2;
+         RUUU1=RUU1-RUU3; IUUU1=IUU1-IUU3;
+         X0[K]=RSSS0+RSSS1; Y0[K]=ISSS0+ISSS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RUUS0+RUUS1; I1=IUUS0+IUUS1;
+            R2=RSUU0+RSUU1; I2=ISUU0+ISUU1;
+            R3=RUSU0+RUSU1; I3=IUSU0+IUSU1;
+            R4=RSSU0+ISSU1; I4=ISSU0-RSSU1;
+            R5=RUUU0+IUUU1; I5=IUUU0-RUUU1;
+            R6=RSUS0+ISUS1; I6=ISUS0-RSUS1;
+            R7=RUSS0+IUSS1; I7=IUSS0-RUSS1;
+            R8=RSSS0-RSSS1; I8=ISSS0-ISSS1;
+            R9=RUUS0-RUUS1; I9=IUUS0-IUUS1;
+            R10=RSUU0-RSUU1; I10=ISUU0-ISUU1;
+            R11=RUSU0-RUSU1; I11=IUSU0-IUSU1;
+            R12=RSSU0-ISSU1; I12=ISSU0+RSSU1;
+            R13=RUUU0-IUUU1; I13=IUUU0+RUUU1;
+            R14=RSUS0-ISUS1; I14=ISUS0+RSUS1;
+            R15=RUSS0-IUSS1; I15=IUSS0+RUSS1;
+            X8[K]=R1*C1+I1*S1; Y8[K]=I1*C1-R1*S1;
+            X4[K]=R2*C2+I2*S2; Y4[K]=I2*C2-R2*S2;
+            X12[K]=R3*C3+I3*S3; Y12[K]=I3*C3-R3*S3;
+            X2[K]=R4*C4+I4*S4; Y2[K]=I4*C4-R4*S4;
+            X10[K]=R5*C5+I5*S5; Y10[K]=I5*C5-R5*S5;
+            X6[K]=R6*C6+I6*S6; Y6[K]=I6*C6-R6*S6;
+            X14[K]=R7*C7+I7*S7; Y14[K]=I7*C7-R7*S7;
+            X1[K]=R8*C8+I8*S8; Y1[K]=I8*C8-R8*S8;
+            X9[K]=R9*C9+I9*S9; Y9[K]=I9*C9-R9*S9;
+            X5[K]=R10*C10+I10*S10; Y5[K]=I10*C10-R10*S10;
+            X13[K]=R11*C11+I11*S11; Y13[K]=I11*C11-R11*S11;
+            X3[K]=R12*C12+I12*S12; Y3[K]=I12*C12-R12*S12;
+            X11[K]=R13*C13+I13*S13; Y11[K]=I13*C13-R13*S13;
+            X7[K]=R14*C14+I14*S14; Y7[K]=I14*C14-R14*S14;
+            X15[K]=R15*C15+I15*S15; Y15[K]=I15*C15-R15*S15;
+         }
+         else
+         {
+            REPORT
+            X8[K]=RUUS0+RUUS1; Y8[K]=IUUS0+IUUS1;
+            X4[K]=RSUU0+RSUU1; Y4[K]=ISUU0+ISUU1;
+            X12[K]=RUSU0+RUSU1; Y12[K]=IUSU0+IUSU1;
+            X2[K]=RSSU0+ISSU1; Y2[K]=ISSU0-RSSU1;
+            X10[K]=RUUU0+IUUU1; Y10[K]=IUUU0-RUUU1;
+            X6[K]=RSUS0+ISUS1; Y6[K]=ISUS0-RSUS1;
+            X14[K]=RUSS0+IUSS1; Y14[K]=IUSS0-RUSS1;
+            X1[K]=RSSS0-RSSS1; Y1[K]=ISSS0-ISSS1;
+            X9[K]=RUUS0-RUUS1; Y9[K]=IUUS0-IUUS1;
+            X5[K]=RSUU0-RSUU1; Y5[K]=ISUU0-ISUU1;
+            X13[K]=RUSU0-RUSU1; Y13[K]=IUSU0-IUSU1;
+            X3[K]=RSSU0-ISSU1; Y3[K]=ISSU0+RSSU1;
+            X11[K]=RUUU0-IUUU1; Y11[K]=IUUU0+RUUU1;
+            X7[K]=RSUS0-ISUS1; Y7[K]=ISUS0+RSUS1;
+            X15[K]=RUSS0-IUSS1; Y15[K]=IUSS0+RUSS1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+// can the number of points be factorised sufficiently
+// for the fft to run
+
+bool FFT_Controller::CanFactor(int PTS)
+{
+   REPORT
+   const int NP = 16, NQ = 10, PMAX=19;
+
+   if (PTS<=1) { REPORT return true; }
+
+   int N = PTS, F = 2, P = 0, Q = 0;
+
+   while (N > 1)
+   {
+      bool fail = true;
+      for (int J = F; J <= PMAX; J++)
+         if (N % J == 0) { fail = false; F=J; break; }
+      if (fail || P >= NP || Q >= NQ) { REPORT return false; }
+      N /= F;
+      if (N % F != 0) Q++; else { N /= F; P++; }
+   }
+
+   return true;    // can factorise
+
+}
+
+bool FFT_Controller::OnlyOldFFT;         // static variable
+
+// **************************** multi radix counter **********************
+
+MultiRadixCounter::MultiRadixCounter(int nx, const SimpleIntArray& rx,
+   SimpleIntArray& vx)
+   : Radix(rx), Value(vx), n(nx), reverse(0),
+      product(1), counter(0), finish(false)
+{
+   REPORT for (int k = 0; k < n; k++) { Value[k] = 0; product *= Radix[k]; }
+}
+
+void MultiRadixCounter::operator++()
+{
+   REPORT
+   counter++; int p = product;
+   for (int k = 0; k < n; k++)
+   {
+      Value[k]++; int p1 = p / Radix[k]; reverse += p1;
+      if (Value[k] == Radix[k]) { REPORT Value[k] = 0; reverse -= p; p = p1; }
+      else { REPORT return; }
+   }
+   finish = true;
+}
+
+
+static int BitReverse(int x, int prod, int n, const SimpleIntArray& f)
+{
+   // x = c[0]+f[0]*(c[1]+f[1]*(c[2]+...
+   // return c[n-1]+f[n-1]*(c[n-2]+f[n-2]*(c[n-3]+...
+   // prod is the product of the f[i]
+   // n is the number of f[i] (don't assume f has the correct length)
+
+   REPORT
+   const int* d = f.Data() + n; int sum = 0; int q = 1;
+   while (n--)
+   {
+      prod /= *(--d);
+      int c = x / prod; x-= c * prod;
+      sum += q * c; q *= *d;
+   }
+   return sum;
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/newmat.h
===================================================================
RCS file: Shared/newmat/newmat.h
diff -N Shared/newmat/newmat.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat.h	23 Jul 2004 21:31:20 -0000	1.2
@@ -0,0 +1,1903 @@
+//$$ newmat.h           definition file for new version of matrix package
+
+// Copyright (C) 1991,2,3,4,7,2000,2,3: R B Davies
+
+#ifndef NEWMAT_LIB
+#define NEWMAT_LIB 0
+
+#include "include.h"
+
+#include "myexcept.h"
+
+
+#ifdef use_namespace
+namespace NEWMAT { using namespace RBD_COMMON; }
+namespace RBD_LIBRARIES { using namespace NEWMAT; }
+namespace NEWMAT {
+#endif
+
+//#define DO_REPORT                     // to activate REPORT
+
+#ifdef NO_LONG_NAMES
+#define UpperTriangularMatrix UTMatrix
+#define LowerTriangularMatrix LTMatrix
+#define SymmetricMatrix SMatrix
+#define DiagonalMatrix DMatrix
+#define BandMatrix BMatrix
+#define UpperBandMatrix UBMatrix
+#define LowerBandMatrix LBMatrix
+#define SymmetricBandMatrix SBMatrix
+#define BandLUMatrix BLUMatrix
+#endif
+
+// ************************** general utilities ****************************/
+
+class GeneralMatrix;
+
+void MatrixErrorNoSpace(const void*);                 // no space handler
+
+class LogAndSign
+// Return from LogDeterminant function
+//    - value of the log plus the sign (+, - or 0)
+{
+   Real log_value;
+   int sign;
+public:
+   LogAndSign() { log_value=0.0; sign=1; }
+   LogAndSign(Real);
+   void operator*=(Real);
+   void PowEq(int k);  // raise to power of k
+   void ChangeSign() { sign = -sign; }
+   Real LogValue() const { return log_value; }
+   int Sign() const { return sign; }
+   Real Value() const;
+   FREE_CHECK(LogAndSign)
+};
+
+// the following class is for counting the number of times a piece of code
+// is executed. It is used for locating any code not executed by test
+// routines. Use turbo GREP locate all places this code is called and
+// check which ones are not accessed.
+// Somewhat implementation dependent as it relies on "cout" still being
+// present when ExeCounter objects are destructed.
+
+#ifdef DO_REPORT
+
+class ExeCounter
+{
+   int line;                                    // code line number
+   int fileid;                                  // file identifier
+   long nexe;                                   // number of executions
+   static int nreports;                         // number of reports
+public:
+   ExeCounter(int,int);
+   void operator++() { nexe++; }
+   ~ExeCounter();                               // prints out reports
+};
+
+#endif
+
+
+// ************************** class MatrixType *****************************/
+
+// Is used for finding the type of a matrix resulting from the binary operations
+// +, -, * and identifying what conversions are permissible.
+// This class must be updated when new matrix types are added.
+
+class GeneralMatrix;                            // defined later
+class BaseMatrix;                               // defined later
+class MatrixInput;                              // defined later
+
+class MatrixType
+{
+public:
+   enum Attribute {  Valid     = 1,
+                     Diagonal  = 2,             // order of these is important
+                     Symmetric = 4,
+                     Band      = 8,
+                     Lower     = 16,
+                     Upper     = 32,
+                     Square    = 64,
+                     Skew      = 128,
+                     LUDeco    = 256,
+                     Ones      = 512 };
+
+   enum            { US = 0,
+                     UT = Valid + Upper + Square,
+                     LT = Valid + Lower + Square,
+                     Rt = Valid,
+                     Sq = Valid + Square,
+                     Sm = Valid + Symmetric + Square,
+                     Sk = Valid + Skew + Square,
+                     Dg = Valid + Diagonal + Band + Lower + Upper + Symmetric
+                        + Square,
+                     Id = Valid + Diagonal + Band + Lower + Upper + Symmetric
+                        + Square + Ones,
+                     RV = Valid,     //   do not separate out
+                     CV = Valid,     //   vectors
+                     BM = Valid + Band + Square,
+                     UB = Valid + Band + Upper + Square,
+                     LB = Valid + Band + Lower + Square,
+                     SB = Valid + Band + Symmetric + Square,
+                     Ct = Valid + LUDeco + Square,
+                     BC = Valid + Band + LUDeco + Square,
+                     Mask = ~Square
+                   };
+
+
+   static int nTypes() { return 12; }          // number of different types
+					       // exclude Ct, US, BC
+public:
+   int attribute;
+   bool DataLossOK;                            // true if data loss is OK when
+                                               // this represents a destination
+public:
+   MatrixType () : DataLossOK(false) {}
+   MatrixType (int i) : attribute(i), DataLossOK(false) {}
+   MatrixType (int i, bool dlok) : attribute(i), DataLossOK(dlok) {}
+   MatrixType (const MatrixType& mt)
+      : attribute(mt.attribute), DataLossOK(mt.DataLossOK) {}
+   void operator=(const MatrixType& mt)
+      { attribute = mt.attribute; DataLossOK = mt.DataLossOK; }
+   void SetDataLossOK() { DataLossOK = true; }
+   int operator+() const { return attribute; }
+   MatrixType operator+(MatrixType mt) const
+      { return MatrixType(attribute & mt.attribute); }
+   MatrixType operator*(const MatrixType&) const;
+   MatrixType SP(const MatrixType&) const;
+   MatrixType KP(const MatrixType&) const;
+   MatrixType operator|(const MatrixType& mt) const
+      { return MatrixType(attribute & mt.attribute & Valid); }
+   MatrixType operator&(const MatrixType& mt) const
+      { return MatrixType(attribute & mt.attribute & Valid); }
+   bool operator>=(MatrixType mt) const
+      { return ( attribute & ~mt.attribute & Mask ) == 0; }
+   bool operator<(MatrixType mt) const         // for MS Visual C++ 4
+      { return ( attribute & ~mt.attribute & Mask ) != 0; }
+   bool operator==(MatrixType t) const
+      { return (attribute == t.attribute); }
+   bool operator!=(MatrixType t) const
+      { return (attribute != t.attribute); }
+   bool operator!() const { return (attribute & Valid) == 0; }
+   MatrixType i() const;                       // type of inverse
+   MatrixType t() const;                       // type of transpose
+   MatrixType AddEqualEl() const               // Add constant to matrix
+      { return MatrixType(attribute & (Valid + Symmetric + Square)); }
+   MatrixType MultRHS() const;                 // type for rhs of multiply
+   MatrixType sub() const                      // type of submatrix
+      { return MatrixType(attribute & Valid); }
+   MatrixType ssub() const                     // type of sym submatrix
+      { return MatrixType(attribute); }        // not for selection matrix
+   GeneralMatrix* New() const;                 // new matrix of given type
+   GeneralMatrix* New(int,int,BaseMatrix*) const;
+                                               // new matrix of given type
+   const char* Value() const;                  // to print type
+   friend bool Rectangular(MatrixType a, MatrixType b, MatrixType c);
+   friend bool Compare(const MatrixType&, MatrixType&);
+                                               // compare and check conv.
+   bool IsBand() const { return (attribute & Band) != 0; }
+   bool IsDiagonal() const { return (attribute & Diagonal) != 0; }
+   bool IsSymmetric() const { return (attribute & Symmetric) != 0; }
+   bool CannotConvert() const { return (attribute & LUDeco) != 0; }
+                                               // used by operator== 
+   FREE_CHECK(MatrixType)
+};
+
+
+// *********************** class MatrixBandWidth ***********************/
+
+class MatrixBandWidth
+{
+public:
+   int lower;
+   int upper;
+   MatrixBandWidth(const int l, const int u) : lower(l), upper (u) {}
+   MatrixBandWidth(const int i) : lower(i), upper(i) {}
+   MatrixBandWidth operator+(const MatrixBandWidth&) const;
+   MatrixBandWidth operator*(const MatrixBandWidth&) const;
+   MatrixBandWidth minimum(const MatrixBandWidth&) const;
+   MatrixBandWidth t() const { return MatrixBandWidth(upper,lower); }
+   bool operator==(const MatrixBandWidth& bw) const
+      { return (lower == bw.lower) && (upper == bw.upper); }
+   bool operator!=(const MatrixBandWidth& bw) const { return !operator==(bw); }
+   int Upper() const { return upper; }
+   int Lower() const { return lower; }
+   FREE_CHECK(MatrixBandWidth)
+};
+
+
+// ********************* Array length specifier ************************/
+
+// This class is introduced to avoid constructors such as
+//   ColumnVector(int)
+// being used for conversions
+
+class ArrayLengthSpecifier
+{
+   int value;
+public:
+   int Value() const { return value; }
+   ArrayLengthSpecifier(int l) : value(l) {}
+};
+
+// ************************* Matrix routines ***************************/
+
+
+class MatrixRowCol;                             // defined later
+class MatrixRow;
+class MatrixCol;
+class MatrixColX;
+
+class GeneralMatrix;                            // defined later
+class AddedMatrix;
+class MultipliedMatrix;
+class SubtractedMatrix;
+class SPMatrix;
+class KPMatrix;
+class ConcatenatedMatrix;
+class StackedMatrix;
+class SolvedMatrix;
+class ShiftedMatrix;
+class NegShiftedMatrix;
+class ScaledMatrix;
+class TransposedMatrix;
+class ReversedMatrix;
+class NegatedMatrix;
+class InvertedMatrix;
+class RowedMatrix;
+class ColedMatrix;
+class DiagedMatrix;
+class MatedMatrix;
+class GetSubMatrix;
+class ReturnMatrix;
+class Matrix;
+class SquareMatrix;
+class nricMatrix;
+class RowVector;
+class ColumnVector;
+class SymmetricMatrix;
+class UpperTriangularMatrix;
+class LowerTriangularMatrix;
+class DiagonalMatrix;
+class CroutMatrix;
+class BandMatrix;
+class LowerBandMatrix;
+class UpperBandMatrix;
+class SymmetricBandMatrix;
+class LinearEquationSolver;
+class GenericMatrix;
+
+
+#define MatrixTypeUnSp 0
+//static MatrixType MatrixTypeUnSp(MatrixType::US);
+//						// AT&T needs this
+
+class BaseMatrix : public Janitor               // base of all matrix classes
+{
+protected:
+   virtual int search(const BaseMatrix*) const = 0;
+						// count number of times matrix
+   						// is referred to
+
+public:
+   virtual GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp) = 0;
+						// evaluate temporary
+   // for old version of G++
+   //   virtual GeneralMatrix* Evaluate(MatrixType mt) = 0;
+   //   GeneralMatrix* Evaluate() { return Evaluate(MatrixTypeUnSp); }
+   AddedMatrix operator+(const BaseMatrix&) const;    // results of operations
+   MultipliedMatrix operator*(const BaseMatrix&) const;
+   SubtractedMatrix operator-(const BaseMatrix&) const;
+   ConcatenatedMatrix operator|(const BaseMatrix&) const;
+   StackedMatrix operator&(const BaseMatrix&) const;
+   ShiftedMatrix operator+(Real) const;
+   ScaledMatrix operator*(Real) const;
+   ScaledMatrix operator/(Real) const;
+   ShiftedMatrix operator-(Real) const;
+   TransposedMatrix t() const;
+//   TransposedMatrix t;
+   NegatedMatrix operator-() const;                   // change sign of elements
+   ReversedMatrix Reverse() const;
+   InvertedMatrix i() const;
+//   InvertedMatrix i;
+   RowedMatrix AsRow() const;
+   ColedMatrix AsColumn() const;
+   DiagedMatrix AsDiagonal() const;
+   MatedMatrix AsMatrix(int,int) const;
+   GetSubMatrix SubMatrix(int,int,int,int) const;
+   GetSubMatrix SymSubMatrix(int,int) const;
+   GetSubMatrix Row(int) const;
+   GetSubMatrix Rows(int,int) const;
+   GetSubMatrix Column(int) const;
+   GetSubMatrix Columns(int,int) const;
+   Real AsScalar() const;                      // conversion of 1 x 1 matrix
+   virtual LogAndSign LogDeterminant() const;
+   Real Determinant() const;
+   virtual Real SumSquare() const;
+   Real NormFrobenius() const;
+   virtual Real SumAbsoluteValue() const;
+   virtual Real Sum() const;
+   virtual Real MaximumAbsoluteValue() const;
+   virtual Real MaximumAbsoluteValue1(int& i) const;
+   virtual Real MaximumAbsoluteValue2(int& i, int& j) const;
+   virtual Real MinimumAbsoluteValue() const;
+   virtual Real MinimumAbsoluteValue1(int& i) const;
+   virtual Real MinimumAbsoluteValue2(int& i, int& j) const;
+   virtual Real Maximum() const;
+   virtual Real Maximum1(int& i) const;
+   virtual Real Maximum2(int& i, int& j) const;
+   virtual Real Minimum() const;
+   virtual Real Minimum1(int& i) const;
+   virtual Real Minimum2(int& i, int& j) const;
+   virtual Real Trace() const;
+   Real Norm1() const;
+   Real NormInfinity() const;
+   virtual MatrixBandWidth BandWidth() const;  // bandwidths of band matrix
+   virtual void CleanUp() {}                   // to clear store
+   void IEQND() const;                         // called by ineq. ops
+//   virtual ReturnMatrix Reverse() const;       // reverse order of elements
+//protected:
+//   BaseMatrix() : t(this), i(this) {}
+
+   friend class GeneralMatrix;
+   friend class Matrix;
+   friend class SquareMatrix;
+   friend class nricMatrix;
+   friend class RowVector;
+   friend class ColumnVector;
+   friend class SymmetricMatrix;
+   friend class UpperTriangularMatrix;
+   friend class LowerTriangularMatrix;
+   friend class DiagonalMatrix;
+   friend class CroutMatrix;
+   friend class BandMatrix;
+   friend class LowerBandMatrix;
+   friend class UpperBandMatrix;
+   friend class SymmetricBandMatrix;
+   friend class AddedMatrix;
+   friend class MultipliedMatrix;
+   friend class SubtractedMatrix;
+   friend class SPMatrix;
+   friend class KPMatrix;
+   friend class ConcatenatedMatrix;
+   friend class StackedMatrix;
+   friend class SolvedMatrix;
+   friend class ShiftedMatrix;
+   friend class NegShiftedMatrix;
+   friend class ScaledMatrix;
+   friend class TransposedMatrix;
+   friend class ReversedMatrix;
+   friend class NegatedMatrix;
+   friend class InvertedMatrix;
+   friend class RowedMatrix;
+   friend class ColedMatrix;
+   friend class DiagedMatrix;
+   friend class MatedMatrix;
+   friend class GetSubMatrix;
+   friend class ReturnMatrix;
+   friend class LinearEquationSolver;
+   friend class GenericMatrix;
+   NEW_DELETE(BaseMatrix)
+};
+
+
+// ***************************** working classes **************************/
+
+class GeneralMatrix : public BaseMatrix         // declarable matrix types
+{
+   virtual GeneralMatrix* Image() const;        // copy of matrix
+protected:
+   int tag;                                     // shows whether can reuse
+   int nrows_value, ncols_value;                // dimensions
+   int storage;                                 // total store required
+   Real* store;                                 // point to store (0=not set)
+   GeneralMatrix();                             // initialise with no store
+   GeneralMatrix(ArrayLengthSpecifier);         // constructor getting store
+   void Add(GeneralMatrix*, Real);              // sum of GM and Real
+   void Add(Real);                              // add Real to this
+   void NegAdd(GeneralMatrix*, Real);           // Real - GM
+   void NegAdd(Real);                           // this = this - Real
+   void Multiply(GeneralMatrix*, Real);         // product of GM and Real
+   void Multiply(Real);                         // multiply this by Real
+   void Negate(GeneralMatrix*);                 // change sign
+   void Negate();                               // change sign
+   void ReverseElements();                      // internal reverse of elements
+   void ReverseElements(GeneralMatrix*);        // reverse order of elements
+   void operator=(Real);                        // set matrix to constant
+   Real* GetStore();                            // get store or copy
+   GeneralMatrix* BorrowStore(GeneralMatrix*, MatrixType);
+                                                // temporarily access store
+   void GetMatrix(const GeneralMatrix*);        // used by = and initialise
+   void Eq(const BaseMatrix&, MatrixType);      // used by =
+   void Eq(const GeneralMatrix&);               // version with no conversion
+   void Eq(const BaseMatrix&, MatrixType, bool);// used by <<
+   void Eq2(const BaseMatrix&, MatrixType);     // cut down version of Eq
+   int search(const BaseMatrix*) const;
+   virtual GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void CheckConversion(const BaseMatrix&);     // check conversion OK
+   void ReSize(int, int, int);                  // change dimensions
+   virtual short SimpleAddOK(const GeneralMatrix* /*gm*/) { return 0; }
+             // see bandmat.cpp for explanation
+   virtual void MiniCleanUp()
+      { store = 0; storage = 0; nrows_value = 0; ncols_value = 0; tag = -1;}
+             // CleanUp when the data array has already been deleted
+   void PlusEqual(const GeneralMatrix& gm);
+   void MinusEqual(const GeneralMatrix& gm);
+   void PlusEqual(Real f);
+   void MinusEqual(Real f);
+   void swap(GeneralMatrix& gm);                // swap values
+public:
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   virtual MatrixType Type() const = 0;         // type of a matrix
+   int Nrows() const { return nrows_value; }    // get dimensions
+   int Ncols() const { return ncols_value; }
+   int Storage() const { return storage; }
+   Real* Store() const { return store; }
+   // updated names
+   int nrows() const { return nrows_value; }    // get dimensions
+   int ncols() const { return ncols_value; }
+   int size() const { return storage; }
+   Real* data() { return store; }
+   const Real* data() const { return store; }
+   const Real* const_data() const { return store; }
+   virtual ~GeneralMatrix();                    // delete store if set
+   void tDelete();                              // delete if tag permits
+   bool reuse();                                // true if tag allows reuse
+   void Protect() { tag=-1; }                   // cannot delete or reuse
+   int Tag() const { return tag; }
+   bool IsZero() const;                         // test matrix has all zeros
+   void Release() { tag=1; }                    // del store after next use
+   void Release(int t) { tag=t; }               // del store after t accesses
+   void ReleaseAndDelete() { tag=0; }           // delete matrix after use
+   void operator<<(const Real*);                // assignment from an array
+   void operator<<(const int*);                // assignment from an array
+   void operator<<(const BaseMatrix& X)
+      { Eq(X,this->Type(),true); }              // = without checking type
+   void Inject(const GeneralMatrix&);           // copy stored els only
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator*=(const BaseMatrix&);
+   void operator|=(const BaseMatrix&);
+   void operator&=(const BaseMatrix&);
+   void operator+=(Real);
+   void operator-=(Real r) { operator+=(-r); }
+   void operator*=(Real);
+   void operator/=(Real r) { operator*=(1.0/r); }
+   virtual GeneralMatrix* MakeSolver();         // for solving
+   virtual void Solver(MatrixColX&, const MatrixColX&) {}
+   virtual void GetRow(MatrixRowCol&) = 0;      // Get matrix row
+   virtual void RestoreRow(MatrixRowCol&) {}    // Restore matrix row
+   virtual void NextRow(MatrixRowCol&);         // Go to next row
+   virtual void GetCol(MatrixRowCol&) = 0;      // Get matrix col
+   virtual void GetCol(MatrixColX&) = 0;        // Get matrix col
+   virtual void RestoreCol(MatrixRowCol&) {}    // Restore matrix col
+   virtual void RestoreCol(MatrixColX&) {}      // Restore matrix col
+   virtual void NextCol(MatrixRowCol&);         // Go to next col
+   virtual void NextCol(MatrixColX&);           // Go to next col
+   Real SumSquare() const;
+   Real SumAbsoluteValue() const;
+   Real Sum() const;
+   Real MaximumAbsoluteValue1(int& i) const;
+   Real MinimumAbsoluteValue1(int& i) const;
+   Real Maximum1(int& i) const;
+   Real Minimum1(int& i) const;
+   Real MaximumAbsoluteValue() const;
+   Real MaximumAbsoluteValue2(int& i, int& j) const;
+   Real MinimumAbsoluteValue() const;
+   Real MinimumAbsoluteValue2(int& i, int& j) const;
+   Real Maximum() const;
+   Real Maximum2(int& i, int& j) const;
+   Real Minimum() const;
+   Real Minimum2(int& i, int& j) const;
+   LogAndSign LogDeterminant() const;
+   virtual bool IsEqual(const GeneralMatrix&) const;
+                                                // same type, same values
+   void CheckStore() const;                     // check store is non-zero
+   virtual void SetParameters(const GeneralMatrix*) {}
+                                                // set parameters in GetMatrix
+   operator ReturnMatrix() const;               // for building a ReturnMatrix
+   ReturnMatrix ForReturn() const;
+   virtual bool SameStorageType(const GeneralMatrix& A) const;
+   virtual void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   virtual void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   virtual void ReSize(const GeneralMatrix& A);
+   MatrixInput operator<<(Real);                // for loading a list
+   MatrixInput operator<<(int f);
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void CleanUp();                              // to clear store
+
+   friend class Matrix;
+   friend class SquareMatrix;
+   friend class nricMatrix;
+   friend class SymmetricMatrix;
+   friend class UpperTriangularMatrix;
+   friend class LowerTriangularMatrix;
+   friend class DiagonalMatrix;
+   friend class CroutMatrix;
+   friend class RowVector;
+   friend class ColumnVector;
+   friend class BandMatrix;
+   friend class LowerBandMatrix;
+   friend class UpperBandMatrix;
+   friend class SymmetricBandMatrix;
+   friend class BaseMatrix;
+   friend class AddedMatrix;
+   friend class MultipliedMatrix;
+   friend class SubtractedMatrix;
+   friend class SPMatrix;
+   friend class KPMatrix;
+   friend class ConcatenatedMatrix;
+   friend class StackedMatrix;
+   friend class SolvedMatrix;
+   friend class ShiftedMatrix;
+   friend class NegShiftedMatrix;
+   friend class ScaledMatrix;
+   friend class TransposedMatrix;
+   friend class ReversedMatrix;
+   friend class NegatedMatrix;
+   friend class InvertedMatrix;
+   friend class RowedMatrix;
+   friend class ColedMatrix;
+   friend class DiagedMatrix;
+   friend class MatedMatrix;
+   friend class GetSubMatrix;
+   friend class ReturnMatrix;
+   friend class LinearEquationSolver;
+   friend class GenericMatrix;
+   NEW_DELETE(GeneralMatrix)
+};
+
+
+
+class Matrix : public GeneralMatrix             // usual rectangular matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   Matrix() {}
+   ~Matrix() {}
+   Matrix(int, int);                            // standard declaration
+   Matrix(const BaseMatrix&);                   // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const Matrix& m) { Eq(m); }
+   MatrixType Type() const;
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;            // access element
+   Real element(int, int) const;               // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+m*ncols_value; }
+   const Real* operator[](int m) const { return store+m*ncols_value; }
+   // following for Numerical Recipes in C++
+   Matrix(Real, int, int);
+   Matrix(const Real*, int, int);
+#endif
+   Matrix(const Matrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver();
+   Real Trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   virtual void ReSize(int,int);           // change dimensions
+      // virtual so we will catch it being used in a vector called as a matrix
+   void ReSize(const GeneralMatrix& A);
+   Real MaximumAbsoluteValue2(int& i, int& j) const;
+   Real MinimumAbsoluteValue2(int& i, int& j) const;
+   Real Maximum2(int& i, int& j) const;
+   Real Minimum2(int& i, int& j) const;
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(Matrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   friend Real DotProduct(const Matrix& A, const Matrix& B);
+   NEW_DELETE(Matrix)
+};
+
+class SquareMatrix : public Matrix              // square matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   SquareMatrix() {}
+   ~SquareMatrix() {}
+   SquareMatrix(ArrayLengthSpecifier);          // standard declaration
+   SquareMatrix(const BaseMatrix&);             // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SquareMatrix& m) { Eq(m); }
+   void operator=(const Matrix& m);
+   MatrixType Type() const;
+   SquareMatrix(const SquareMatrix& gm) : Matrix() { GetMatrix(&gm); }
+   SquareMatrix(const Matrix& gm);
+   void ReSize(int);                            // change dimensions
+   virtual void ReSize(int,int);                // change dimensions
+      // virtual so we will catch it being used in a vector called as a matrix
+   void ReSize(const GeneralMatrix& A);
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(SquareMatrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(SquareMatrix)
+};
+
+class nricMatrix : public Matrix                // for use with Numerical
+                                                // Recipes in C
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+   Real** row_pointer;                          // points to rows
+   void MakeRowPointer();                       // build rowpointer
+   void DeleteRowPointer();
+public:
+   nricMatrix() {}
+   nricMatrix(int m, int n)                     // standard declaration
+      :  Matrix(m,n) { MakeRowPointer(); }
+   nricMatrix(const BaseMatrix& bm)             // evaluate BaseMatrix
+      :  Matrix(bm) { MakeRowPointer(); }
+   void operator=(const BaseMatrix& bm)
+      { DeleteRowPointer(); Matrix::operator=(bm); MakeRowPointer(); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const nricMatrix& m)
+      { DeleteRowPointer(); Eq(m); MakeRowPointer(); }
+   void operator<<(const BaseMatrix& X)
+      { DeleteRowPointer(); Eq(X,this->Type(),true); MakeRowPointer(); }
+   nricMatrix(const nricMatrix& gm) : Matrix() { GetMatrix(&gm); MakeRowPointer(); }
+   void ReSize(int m, int n)               // change dimensions
+      { DeleteRowPointer(); Matrix::ReSize(m,n); MakeRowPointer(); }
+   void ReSize(const GeneralMatrix& A);
+   ~nricMatrix() { DeleteRowPointer(); }
+   Real** nric() const { CheckStore(); return row_pointer-1; }
+   void CleanUp();                                // to clear store
+   void MiniCleanUp();
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(nricMatrix& gm);
+   NEW_DELETE(nricMatrix)
+};
+
+class SymmetricMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   SymmetricMatrix() {}
+   ~SymmetricMatrix() {}
+   SymmetricMatrix(ArrayLengthSpecifier);
+   SymmetricMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SymmetricMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(m*(m+1))/2; }
+   const Real* operator[](int m) const { return store+(m*(m+1))/2; }
+#endif
+   MatrixType Type() const;
+   SymmetricMatrix(const SymmetricMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   Real SumSquare() const;
+   Real SumAbsoluteValue() const;
+   Real Sum() const;
+   Real Trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX&);
+	GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int);                       // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   void operator+=(const SymmetricMatrix& M) { PlusEqual(M); }
+   void operator-=(const SymmetricMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(SymmetricMatrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(SymmetricMatrix)
+};
+
+class UpperTriangularMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   UpperTriangularMatrix() {}
+   ~UpperTriangularMatrix() {}
+   UpperTriangularMatrix(ArrayLengthSpecifier);
+   void operator=(const BaseMatrix&);
+   void operator=(const UpperTriangularMatrix& m) { Eq(m); }
+   UpperTriangularMatrix(const BaseMatrix&);
+   UpperTriangularMatrix(const UpperTriangularMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+m*ncols_value-(m*(m+1))/2; }
+   const Real* operator[](int m) const
+      { return store+m*ncols_value-(m*(m+1))/2; }
+#endif
+   MatrixType Type() const;
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign LogDeterminant() const;
+   Real Trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   void ReSize(int);                       // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   MatrixBandWidth BandWidth() const;
+   void operator+=(const UpperTriangularMatrix& M) { PlusEqual(M); }
+   void operator-=(const UpperTriangularMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(UpperTriangularMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(UpperTriangularMatrix)
+};
+
+class LowerTriangularMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   LowerTriangularMatrix() {}
+   ~LowerTriangularMatrix() {}
+   LowerTriangularMatrix(ArrayLengthSpecifier);
+   LowerTriangularMatrix(const LowerTriangularMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   LowerTriangularMatrix(const BaseMatrix& M);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const LowerTriangularMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(m*(m+1))/2; }
+   const Real* operator[](int m) const { return store+(m*(m+1))/2; }
+#endif
+   MatrixType Type() const;
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign LogDeterminant() const;
+   Real Trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   void ReSize(int);                       // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   MatrixBandWidth BandWidth() const;
+   void operator+=(const LowerTriangularMatrix& M) { PlusEqual(M); }
+   void operator-=(const LowerTriangularMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(LowerTriangularMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(LowerTriangularMatrix)
+};
+
+class DiagonalMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   DiagonalMatrix() {}
+   ~DiagonalMatrix() {}
+   DiagonalMatrix(ArrayLengthSpecifier);
+   DiagonalMatrix(const BaseMatrix&);
+   DiagonalMatrix(const DiagonalMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const DiagonalMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& operator()(int);                       // access element
+   Real operator()(int, int) const;             // access element
+   Real operator()(int) const;
+   Real& element(int, int);                     // access element
+   Real& element(int);                          // access element
+   Real element(int, int) const;                // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+#endif
+   MatrixType Type() const;
+
+   LogAndSign LogDeterminant() const;
+   Real Trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int);                       // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   MatrixBandWidth BandWidth() const;
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void operator+=(const DiagonalMatrix& M) { PlusEqual(M); }
+   void operator-=(const DiagonalMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(DiagonalMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(DiagonalMatrix)
+};
+
+class RowVector : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   RowVector() { nrows_value = 1; }
+   ~RowVector() {}
+   RowVector(ArrayLengthSpecifier n) : Matrix(1,n.Value()) {}
+   RowVector(const BaseMatrix&);
+   RowVector(const RowVector& gm) : Matrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const RowVector& m) { Eq(m); }
+   Real& operator()(int);                       // access element
+   Real& element(int);                          // access element
+   Real operator()(int) const;                  // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+   // following for Numerical Recipes in C++
+   RowVector(Real a, int n) : Matrix(a, 1, n) {}
+   RowVector(const Real* a, int n) : Matrix(a, 1, n) {}
+#endif
+   MatrixType Type() const;
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX& c);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int);                       // change dimensions
+   void ReSize(int,int);                   // in case access is matrix
+   void ReSize(const GeneralMatrix& A);
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   void CleanUp();                              // to clear store
+   void MiniCleanUp()
+      { store = 0; storage = 0; nrows_value = 1; ncols_value = 0; tag = -1; }
+   // friend ReturnMatrix GetMatrixRow(Matrix& A, int row);
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(RowVector& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(RowVector)
+};
+
+class ColumnVector : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   ColumnVector() { ncols_value = 1; }
+   ~ColumnVector() {}
+   ColumnVector(ArrayLengthSpecifier n) : Matrix(n.Value(),1) {}
+   ColumnVector(const BaseMatrix&);
+   ColumnVector(const ColumnVector& gm) : Matrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const ColumnVector& m) { Eq(m); }
+   Real& operator()(int);                       // access element
+   Real& element(int);                          // access element
+   Real operator()(int) const;                  // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+   // following for Numerical Recipes in C++
+   ColumnVector(Real a, int m) : Matrix(a, m, 1) {}
+   ColumnVector(const Real* a, int m) : Matrix(a, m, 1) {}
+#endif
+   MatrixType Type() const;
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int);                       // change dimensions
+   void ReSize(int,int);                   // in case access is matrix
+   void ReSize(const GeneralMatrix& A);
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   void CleanUp();                              // to clear store
+   void MiniCleanUp()
+      { store = 0; storage = 0; nrows_value = 0; ncols_value = 1; tag = -1; }
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(ColumnVector& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(ColumnVector)
+};
+
+class CroutMatrix : public GeneralMatrix        // for LU decomposition
+{
+   int* indx;
+   bool d;
+   bool sing;
+   void ludcmp();
+   void operator=(const CroutMatrix& m) {}     // not allowed
+public:
+   CroutMatrix(const BaseMatrix&);
+   MatrixType Type() const;
+   void lubksb(Real*, int=0);
+   ~CroutMatrix();
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   LogAndSign LogDeterminant() const;
+   void Solver(MatrixColX&, const MatrixColX&);
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); }
+   void CleanUp();                                // to clear store
+   void MiniCleanUp();
+   bool IsEqual(const GeneralMatrix&) const;
+   bool IsSingular() const { return sing; }
+   void swap(CroutMatrix& gm);
+   NEW_DELETE(CroutMatrix)
+};
+
+// ***************************** band matrices ***************************/
+
+class BandMatrix : public GeneralMatrix         // band matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+protected:
+   void CornerClear() const;                    // set unused elements to zero
+   short SimpleAddOK(const GeneralMatrix* gm);
+public:
+   int lower, upper;                            // band widths
+   BandMatrix() { lower=0; upper=0; CornerClear(); }
+   ~BandMatrix() {}
+   BandMatrix(int n,int lb,int ub) { ReSize(n,lb,ub); CornerClear(); }
+                                                // standard declaration
+   BandMatrix(const BaseMatrix&);               // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const BandMatrix& m) { Eq(m); }
+   MatrixType Type() const;
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(upper+lower)*m+lower; }
+   const Real* operator[](int m) const { return store+(upper+lower)*m+lower; }
+#endif
+   BandMatrix(const BandMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   LogAndSign LogDeterminant() const;
+   GeneralMatrix* MakeSolver();
+   Real Trace() const;
+   Real SumSquare() const { CornerClear(); return GeneralMatrix::SumSquare(); }
+   Real SumAbsoluteValue() const
+      { CornerClear(); return GeneralMatrix::SumAbsoluteValue(); }
+   Real Sum() const
+      { CornerClear(); return GeneralMatrix::Sum(); }
+   Real MaximumAbsoluteValue() const
+      { CornerClear(); return GeneralMatrix::MaximumAbsoluteValue(); }
+   Real MinimumAbsoluteValue() const
+      { int i, j; return GeneralMatrix::MinimumAbsoluteValue2(i, j); }
+   Real Maximum() const { int i, j; return GeneralMatrix::Maximum2(i, j); }
+   Real Minimum() const { int i, j; return GeneralMatrix::Minimum2(i, j); }
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   virtual void ReSize(int, int, int);             // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   bool SameStorageType(const GeneralMatrix& A) const;
+   void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   MatrixBandWidth BandWidth() const;
+   void SetParameters(const GeneralMatrix*);
+   MatrixInput operator<<(Real);                // will give error
+   MatrixInput operator<<(int f);
+   void operator<<(const Real* r);              // will give error
+   void operator<<(const int* r);               // will give error
+      // the next is included because Zortech and Borland
+      // cannot find the copy in GeneralMatrix
+   void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); }
+   void swap(BandMatrix& gm);
+   NEW_DELETE(BandMatrix)
+};
+
+class UpperBandMatrix : public BandMatrix       // upper band matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   UpperBandMatrix() {}
+   ~UpperBandMatrix() {}
+   UpperBandMatrix(int n, int ubw)              // standard declaration
+      : BandMatrix(n, 0, ubw) {}
+   UpperBandMatrix(const BaseMatrix&);          // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const UpperBandMatrix& m) { Eq(m); }
+   MatrixType Type() const;
+   UpperBandMatrix(const UpperBandMatrix& gm) : BandMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver() { return this; }
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign LogDeterminant() const;
+   void ReSize(int, int, int);             // change dimensions
+   void ReSize(int n,int ubw)              // change dimensions
+      { BandMatrix::ReSize(n,0,ubw); }
+   void ReSize(const GeneralMatrix& A) { BandMatrix::ReSize(A); }
+   Real& operator()(int, int);
+   Real operator()(int, int) const;
+   Real& element(int, int);
+   Real element(int, int) const;
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+upper*m; }
+   const Real* operator[](int m) const { return store+upper*m; }
+#endif
+   void swap(UpperBandMatrix& gm)
+      { BandMatrix::swap((BandMatrix&)gm); }
+   NEW_DELETE(UpperBandMatrix)
+};
+
+class LowerBandMatrix : public BandMatrix       // upper band matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   LowerBandMatrix() {}
+   ~LowerBandMatrix() {}
+   LowerBandMatrix(int n, int lbw)              // standard declaration
+      : BandMatrix(n, lbw, 0) {}
+   LowerBandMatrix(const BaseMatrix&);          // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const LowerBandMatrix& m) { Eq(m); }
+   MatrixType Type() const;
+   LowerBandMatrix(const LowerBandMatrix& gm) : BandMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver() { return this; }
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign LogDeterminant() const;
+   void ReSize(int, int, int);             // change dimensions
+   void ReSize(int n,int lbw)             // change dimensions
+      { BandMatrix::ReSize(n,lbw,0); }
+   void ReSize(const GeneralMatrix& A) { BandMatrix::ReSize(A); }
+   Real& operator()(int, int);
+   Real operator()(int, int) const;
+   Real& element(int, int);
+   Real element(int, int) const;
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+lower*(m+1); }
+   const Real* operator[](int m) const { return store+lower*(m+1); }
+#endif
+   void swap(LowerBandMatrix& gm)
+      { BandMatrix::swap((BandMatrix&)gm); }
+   NEW_DELETE(LowerBandMatrix)
+};
+
+class SymmetricBandMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+   void CornerClear() const;                    // set unused elements to zero
+   short SimpleAddOK(const GeneralMatrix* gm);
+public:
+   int lower;                                   // lower band width
+   SymmetricBandMatrix() { lower=0; CornerClear(); }
+   ~SymmetricBandMatrix() {}
+   SymmetricBandMatrix(int n, int lb) { ReSize(n,lb); CornerClear(); }
+   SymmetricBandMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SymmetricBandMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+lower*(m+1); }
+   const Real* operator[](int m) const { return store+lower*(m+1); }
+#endif
+   MatrixType Type() const;
+   SymmetricBandMatrix(const SymmetricBandMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver();
+   Real SumSquare() const;
+   Real SumAbsoluteValue() const;
+   Real Sum() const;
+   Real MaximumAbsoluteValue() const
+      { CornerClear(); return GeneralMatrix::MaximumAbsoluteValue(); }
+   Real MinimumAbsoluteValue() const
+      { int i, j; return GeneralMatrix::MinimumAbsoluteValue2(i, j); }
+   Real Maximum() const { int i, j; return GeneralMatrix::Maximum2(i, j); }
+   Real Minimum() const { int i, j; return GeneralMatrix::Minimum2(i, j); }
+   Real Trace() const;
+   LogAndSign LogDeterminant() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int,int);                       // change dimensions
+   void ReSize(const GeneralMatrix& A);
+   bool SameStorageType(const GeneralMatrix& A) const;
+   void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   MatrixBandWidth BandWidth() const;
+   void SetParameters(const GeneralMatrix*);
+   void operator<<(const Real* r);              // will give error
+   void operator<<(const int* r);               // will give error
+   void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); }
+   void swap(SymmetricBandMatrix& gm);
+   NEW_DELETE(SymmetricBandMatrix)
+};
+
+class BandLUMatrix : public GeneralMatrix
+// for LU decomposition of band matrix
+{
+   int* indx;
+   bool d;
+   bool sing;                                   // true if singular
+   Real* store2;
+   int storage2;
+   void ludcmp();
+   int m1,m2;                                   // lower and upper
+   void operator=(const BandLUMatrix& m) {}     // no allowed
+public:
+   BandLUMatrix(const BaseMatrix&);
+   MatrixType Type() const;
+   void lubksb(Real*, int=0);
+   ~BandLUMatrix();
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   LogAndSign LogDeterminant() const;
+   void Solver(MatrixColX&, const MatrixColX&);
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); }
+   void CleanUp();                                // to clear store
+   void MiniCleanUp();
+   bool IsEqual(const GeneralMatrix&) const;
+   bool IsSingular() const { return sing; }
+   void swap(BandLUMatrix& gm);
+   NEW_DELETE(BandLUMatrix)
+};
+
+// ************************** special matrices ****************************
+
+class IdentityMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;          // copy of matrix
+public:
+   IdentityMatrix() {}
+   ~IdentityMatrix() {}
+   IdentityMatrix(ArrayLengthSpecifier n) : GeneralMatrix(1)
+      { nrows_value = ncols_value = n.Value(); *store = 1; }
+   IdentityMatrix(const IdentityMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   IdentityMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(const IdentityMatrix& m) { Eq(m); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   MatrixType Type() const;
+
+   LogAndSign LogDeterminant() const;
+   Real Trace() const;
+   Real SumSquare() const;
+   Real SumAbsoluteValue() const;
+   Real Sum() const { return Trace(); }
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void ReSize(int n);
+   void ReSize(const GeneralMatrix& A);
+   MatrixBandWidth BandWidth() const;
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void swap(IdentityMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(IdentityMatrix)
+};
+
+
+
+
+// ************************** GenericMatrix class ************************/
+
+class GenericMatrix : public BaseMatrix
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix* bm) const;
+   friend class BaseMatrix;
+public:
+   GenericMatrix() : gm(0) {}
+   GenericMatrix(const BaseMatrix& bm)
+      { gm = ((BaseMatrix&)bm).Evaluate(); gm = gm->Image(); }
+   GenericMatrix(const GenericMatrix& bm) : BaseMatrix()
+      { gm = bm.gm->Image(); }
+   void operator=(const GenericMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator*=(const BaseMatrix&);
+   void operator|=(const BaseMatrix&);
+   void operator&=(const BaseMatrix&);
+   void operator+=(Real);
+   void operator-=(Real r) { operator+=(-r); }
+   void operator*=(Real);
+   void operator/=(Real r) { operator*=(1.0/r); }
+   ~GenericMatrix() { delete gm; }
+   void CleanUp() { delete gm; gm = 0; }
+   void Release() { gm->Release(); }
+   GeneralMatrix* Evaluate(MatrixType = MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   void swap(GenericMatrix& x);
+   NEW_DELETE(GenericMatrix)
+};
+
+// *************************** temporary classes *************************/
+
+class MultipliedMatrix : public BaseMatrix
+{
+protected:
+   // if these union statements cause problems, simply remove them
+   // and declare the items individually
+   union { const BaseMatrix* bm1; GeneralMatrix* gm1; };
+						  // pointers to summands
+   union { const BaseMatrix* bm2; GeneralMatrix* gm2; };
+   MultipliedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : bm1(bm1x),bm2(bm2x) {}
+   int search(const BaseMatrix*) const;
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~MultipliedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(MultipliedMatrix)
+};
+
+class AddedMatrix : public MultipliedMatrix
+{
+protected:
+   AddedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~AddedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(AddedMatrix)
+};
+
+class SPMatrix : public AddedMatrix
+{
+protected:
+   SPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : AddedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~SPMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+
+   friend SPMatrix SP(const BaseMatrix&, const BaseMatrix&);
+
+   NEW_DELETE(SPMatrix)
+};
+
+class KPMatrix : public MultipliedMatrix
+{
+protected:
+   KPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~KPMatrix() {}
+   MatrixBandWidth BandWidth() const;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend KPMatrix KP(const BaseMatrix&, const BaseMatrix&);
+   NEW_DELETE(KPMatrix)
+};
+
+class ConcatenatedMatrix : public MultipliedMatrix
+{
+protected:
+   ConcatenatedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ConcatenatedMatrix() {}
+   MatrixBandWidth BandWidth() const;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(ConcatenatedMatrix)
+};
+
+class StackedMatrix : public ConcatenatedMatrix
+{
+protected:
+   StackedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : ConcatenatedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~StackedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(StackedMatrix)
+};
+
+class SolvedMatrix : public MultipliedMatrix
+{
+   SolvedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+   friend class BaseMatrix;
+   friend class InvertedMatrix;                        // for operator*
+public:
+   ~SolvedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(SolvedMatrix)
+};
+
+class SubtractedMatrix : public AddedMatrix
+{
+   SubtractedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : AddedMatrix(bm1x,bm2x) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~SubtractedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(SubtractedMatrix)
+};
+
+class ShiftedMatrix : public BaseMatrix
+{
+protected:
+   union { const BaseMatrix* bm; GeneralMatrix* gm; };
+   Real f;
+   ShiftedMatrix(const BaseMatrix* bmx, Real fx) : bm(bmx),f(fx) {}
+   int search(const BaseMatrix*) const;
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ShiftedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend ShiftedMatrix operator+(Real f, const BaseMatrix& BM);
+   NEW_DELETE(ShiftedMatrix)
+};
+
+class NegShiftedMatrix : public ShiftedMatrix
+{
+protected:
+   NegShiftedMatrix(Real fx, const BaseMatrix* bmx) : ShiftedMatrix(bmx,fx) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~NegShiftedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend NegShiftedMatrix operator-(Real, const BaseMatrix&);
+   NEW_DELETE(NegShiftedMatrix)
+};
+
+class ScaledMatrix : public ShiftedMatrix
+{
+   ScaledMatrix(const BaseMatrix* bmx, Real fx) : ShiftedMatrix(bmx,fx) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ScaledMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   friend ScaledMatrix operator*(Real f, const BaseMatrix& BM);
+   NEW_DELETE(ScaledMatrix)
+};
+
+class NegatedMatrix : public BaseMatrix
+{
+protected:
+   union { const BaseMatrix* bm; GeneralMatrix* gm; };
+   NegatedMatrix(const BaseMatrix* bmx) : bm(bmx) {}
+   int search(const BaseMatrix*) const;
+private:
+   friend class BaseMatrix;
+public:
+   ~NegatedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(NegatedMatrix)
+};
+
+class TransposedMatrix : public NegatedMatrix
+{
+   TransposedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~TransposedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(TransposedMatrix)
+};
+
+class ReversedMatrix : public NegatedMatrix
+{
+   ReversedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~ReversedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(ReversedMatrix)
+};
+
+class InvertedMatrix : public NegatedMatrix
+{
+   InvertedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+public:
+   ~InvertedMatrix() {}
+   SolvedMatrix operator*(const BaseMatrix&) const;       // inverse(A) * B
+   ScaledMatrix operator*(Real t) const { return BaseMatrix::operator*(t); }
+   friend class BaseMatrix;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(InvertedMatrix)
+};
+
+class RowedMatrix : public NegatedMatrix
+{
+   RowedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~RowedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(RowedMatrix)
+};
+
+class ColedMatrix : public NegatedMatrix
+{
+   ColedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~ColedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(ColedMatrix)
+};
+
+class DiagedMatrix : public NegatedMatrix
+{
+   DiagedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~DiagedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(DiagedMatrix)
+};
+
+class MatedMatrix : public NegatedMatrix
+{
+   int nr, nc;
+   MatedMatrix(const BaseMatrix* bmx, int nrx, int ncx)
+      : NegatedMatrix(bmx), nr(nrx), nc(ncx) {}
+   friend class BaseMatrix;
+public:
+   ~MatedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(MatedMatrix)
+};
+
+class ReturnMatrix : public BaseMatrix    // for matrix return
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix*) const;
+public:
+   ~ReturnMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend class BaseMatrix;
+   ReturnMatrix(const ReturnMatrix& tm) : BaseMatrix(), gm(tm.gm) {}
+   ReturnMatrix(const GeneralMatrix* gmx) : gm((GeneralMatrix*&)gmx) {}
+//   ReturnMatrix(GeneralMatrix&);
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(ReturnMatrix)
+};
+
+
+// ************************** submatrices ******************************/
+
+class GetSubMatrix : public NegatedMatrix
+{
+   int row_skip;
+   int row_number;
+   int col_skip;
+   int col_number;
+   bool IsSym;
+
+   GetSubMatrix
+      (const BaseMatrix* bmx, int rs, int rn, int cs, int cn, bool is)
+      : NegatedMatrix(bmx),
+      row_skip(rs), row_number(rn), col_skip(cs), col_number(cn), IsSym(is) {}
+   void SetUpLHS();
+   friend class BaseMatrix;
+public:
+   GetSubMatrix(const GetSubMatrix& g)
+      : NegatedMatrix(g.bm), row_skip(g.row_skip), row_number(g.row_number),
+      col_skip(g.col_skip), col_number(g.col_number), IsSym(g.IsSym) {}
+   ~GetSubMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   void operator=(const BaseMatrix&);
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator=(const GetSubMatrix& m) { operator=((const BaseMatrix&)m); }
+   void operator<<(const BaseMatrix&);
+   void operator<<(const Real*);                // copy from array
+   void operator<<(const int*);                 // copy from array
+   MatrixInput operator<<(Real);                // for loading a list
+   MatrixInput operator<<(int f);
+   void operator=(Real);                        // copy from constant
+   void operator+=(Real);                       // add constant
+   void operator-=(Real r) { operator+=(-r); }  // subtract constant
+   void operator*=(Real);                       // multiply by constant
+   void operator/=(Real r) { operator*=(1.0/r); } // divide by constant
+   void Inject(const GeneralMatrix&);           // copy stored els only
+   MatrixBandWidth BandWidth() const;
+   NEW_DELETE(GetSubMatrix)
+};
+
+// ******************** linear equation solving ****************************/
+
+class LinearEquationSolver : public BaseMatrix
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix*) const { return 0; }
+   friend class BaseMatrix;
+public:
+   LinearEquationSolver(const BaseMatrix& bm);
+   ~LinearEquationSolver() { delete gm; }
+   void CleanUp() { delete gm; } 
+   GeneralMatrix* Evaluate(MatrixType) { return gm; }
+   // probably should have an error message if MatrixType != UnSp
+   NEW_DELETE(LinearEquationSolver)
+};
+
+// ************************** matrix input *******************************/
+
+class MatrixInput          // for reading a list of values into a matrix
+                           // the difficult part is detecting a mismatch
+                           // in the number of elements
+{
+   int n;                  // number values still to be read
+   Real* r;                // pointer to next location to be read to
+public:
+   MatrixInput(const MatrixInput& mi) : n(mi.n), r(mi.r) {}
+   MatrixInput(int nx, Real* rx) : n(nx), r(rx) {}
+   ~MatrixInput();
+   MatrixInput operator<<(Real);
+   MatrixInput operator<<(int f);
+   friend class GeneralMatrix;
+};
+
+
+
+// **************** a very simple integer array class ********************/
+
+// A minimal array class to imitate a C style array but giving dynamic storage
+// mostly intended for internal use by newmat
+
+class SimpleIntArray : public Janitor
+{
+protected:
+   int* a;                    // pointer to the array
+   int n;                     // length of the array
+public:
+   SimpleIntArray(int xn);    // build an array length xn
+   SimpleIntArray() : a(0), n(0) {}  // build an array length 0
+   ~SimpleIntArray();         // return the space to memory
+   int& operator[](int i);    // access element of the array - start at 0
+   int operator[](int i) const;
+			      // access element of constant array
+   void operator=(int ai);    // set the array equal to a constant
+   void operator=(const SimpleIntArray& b);
+			      // copy the elements of an array
+   SimpleIntArray(const SimpleIntArray& b);
+			      // make a new array equal to an existing one
+   int Size() const { return n; }
+			      // return the size of the array
+   int size() const { return n; }
+			      // return the size of the array
+   int* Data() { return a; }  // pointer to the data
+   const int* Data() const { return a; }  // pointer to the data
+   int* data() { return a; }  // pointer to the data
+   const int* data() const { return a; }  // pointer to the data
+   const int* const_data() const { return a; }  // pointer to the data
+   void ReSize(int i, bool keep = false);
+                              // change length, keep data if keep = true
+   void resize(int i, bool keep = false) { ReSize(i, keep); }
+                              // change length, keep data if keep = true
+   void CleanUp() { ReSize(0); }
+   NEW_DELETE(SimpleIntArray)
+};
+
+// ********************** C subscript classes ****************************
+
+class RealStarStar
+{
+   Real** a;
+public:
+   RealStarStar(Matrix& A);
+   ~RealStarStar() { delete [] a; }
+   operator Real**() { return a; }
+};
+
+class ConstRealStarStar
+{
+   const Real** a;
+public:
+   ConstRealStarStar(const Matrix& A);
+   ~ConstRealStarStar() { delete [] a; }
+   operator const Real**() { return a; }
+};
+
+// *************************** exceptions ********************************/
+
+class NPDException : public Runtime_error     // Not positive definite
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   NPDException(const GeneralMatrix&);
+};
+
+class ConvergenceException : public Runtime_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   ConvergenceException(const GeneralMatrix& A);
+   ConvergenceException(const char* c);
+};
+
+class SingularException : public Runtime_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   SingularException(const GeneralMatrix& A);
+};
+
+class OverflowException : public Runtime_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   OverflowException(const char* c);
+};
+
+class ProgramException : public Logic_error
+{
+protected:
+   ProgramException();
+public:
+   static unsigned long Select;          // for identifying exception
+   ProgramException(const char* c);
+   ProgramException(const char* c, const GeneralMatrix&);
+   ProgramException(const char* c, const GeneralMatrix&, const GeneralMatrix&);
+   ProgramException(const char* c, MatrixType, MatrixType);
+};
+
+class IndexException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   IndexException(int i, const GeneralMatrix& A);
+   IndexException(int i, int j, const GeneralMatrix& A);
+   // next two are for access via element function
+   IndexException(int i, const GeneralMatrix& A, bool);
+   IndexException(int i, int j, const GeneralMatrix& A, bool);
+};
+
+class VectorException : public Logic_error    // cannot convert to vector
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   VectorException();
+   VectorException(const GeneralMatrix& A);
+};
+
+class NotSquareException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   NotSquareException(const GeneralMatrix& A);
+   NotSquareException();
+};
+
+class SubMatrixDimensionException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   SubMatrixDimensionException();
+};
+
+class IncompatibleDimensionsException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   IncompatibleDimensionsException();
+   IncompatibleDimensionsException(const GeneralMatrix&, const GeneralMatrix&);
+};
+
+class NotDefinedException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   NotDefinedException(const char* op, const char* matrix);
+};
+
+class CannotBuildException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   CannotBuildException(const char* matrix);
+};
+
+
+class InternalException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   InternalException(const char* c);
+};
+
+// ************************ functions ************************************ //
+
+bool operator==(const GeneralMatrix& A, const GeneralMatrix& B);
+bool operator==(const BaseMatrix& A, const BaseMatrix& B);
+inline bool operator!=(const GeneralMatrix& A, const GeneralMatrix& B)
+   { return ! (A==B); }
+inline bool operator!=(const BaseMatrix& A, const BaseMatrix& B)
+   { return ! (A==B); }
+
+   // inequality operators are dummies included for compatibility
+   // with STL. They throw an exception if actually called.
+inline bool operator<=(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator>=(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator<(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator>(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+
+bool IsZero(const BaseMatrix& A);
+
+Matrix CrossProduct(const Matrix& A, const Matrix& B);
+ReturnMatrix CrossProductRows(const Matrix& A, const Matrix& B);
+ReturnMatrix CrossProductColumns(const Matrix& A, const Matrix& B);
+
+
+// ********************* inline functions ******************************** //
+
+
+inline LogAndSign LogDeterminant(const BaseMatrix& B)
+   { return B.LogDeterminant(); }
+inline Real Determinant(const BaseMatrix& B)
+   { return B.Determinant(); }
+inline Real SumSquare(const BaseMatrix& B) { return B.SumSquare(); }
+inline Real NormFrobenius(const BaseMatrix& B) { return B.NormFrobenius(); }
+inline Real Trace(const BaseMatrix& B) { return B.Trace(); }
+inline Real SumAbsoluteValue(const BaseMatrix& B)
+   { return B.SumAbsoluteValue(); }
+inline Real Sum(const BaseMatrix& B)
+   { return B.Sum(); }
+inline Real MaximumAbsoluteValue(const BaseMatrix& B)
+   { return B.MaximumAbsoluteValue(); }
+inline Real MinimumAbsoluteValue(const BaseMatrix& B)
+   { return B.MinimumAbsoluteValue(); }
+inline Real Maximum(const BaseMatrix& B) { return B.Maximum(); }
+inline Real Minimum(const BaseMatrix& B) { return B.Minimum(); }
+inline Real Norm1(const BaseMatrix& B) { return B.Norm1(); }
+inline Real Norm1(RowVector& RV) { return RV.MaximumAbsoluteValue(); }
+inline Real NormInfinity(const BaseMatrix& B) { return B.NormInfinity(); }
+inline Real NormInfinity(ColumnVector& CV)
+   { return CV.MaximumAbsoluteValue(); }
+inline bool IsZero(const GeneralMatrix& A) { return A.IsZero(); }
+
+
+inline MatrixInput MatrixInput::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput GeneralMatrix::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput BandMatrix::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput GetSubMatrix::operator<<(int f) { return *this << (Real)f; }
+
+inline void swap(Matrix& A, Matrix& B) { A.swap(B); }
+inline void swap(SquareMatrix& A, SquareMatrix& B) { A.swap(B); }
+inline void swap(nricMatrix& A, nricMatrix& B) { A.swap(B); }
+inline void swap(UpperTriangularMatrix& A, UpperTriangularMatrix& B)
+   { A.swap(B); }
+inline void swap(LowerTriangularMatrix& A, LowerTriangularMatrix& B)
+   { A.swap(B); }
+inline void swap(SymmetricMatrix& A, SymmetricMatrix& B) { A.swap(B); }
+inline void swap(DiagonalMatrix& A, DiagonalMatrix& B) { A.swap(B); }
+inline void swap(RowVector& A, RowVector& B) { A.swap(B); }
+inline void swap(ColumnVector& A, ColumnVector& B) { A.swap(B); }
+inline void swap(CroutMatrix& A, CroutMatrix& B) { A.swap(B); }
+inline void swap(BandMatrix& A, BandMatrix& B) { A.swap(B); }
+inline void swap(UpperBandMatrix& A, UpperBandMatrix& B) { A.swap(B); }
+inline void swap(LowerBandMatrix& A, LowerBandMatrix& B) { A.swap(B); }
+inline void swap(SymmetricBandMatrix& A, SymmetricBandMatrix& B) { A.swap(B); }
+inline void swap(BandLUMatrix& A, BandLUMatrix& B) { A.swap(B); }
+inline void swap(IdentityMatrix& A, IdentityMatrix& B) { A.swap(B); }
+inline void swap(GenericMatrix& A, GenericMatrix& B) { A.swap(B); }
+
+
+#ifdef OPT_COMPATIBLE                    // for compatibility with opt++
+
+inline Real Norm2(const ColumnVector& CV) { return CV.NormFrobenius(); }
+inline Real Dot(ColumnVector& CV1, ColumnVector& CV2)
+   { return DotProduct(CV1, CV2); }
+
+#endif
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+#endif
+
+// body file: newmat1.cpp
+// body file: newmat2.cpp
+// body file: newmat3.cpp
+// body file: newmat4.cpp
+// body file: newmat5.cpp
+// body file: newmat6.cpp
+// body file: newmat7.cpp
+// body file: newmat8.cpp
+// body file: newmatex.cpp
+// body file: bandmat.cpp
+// body file: submat.cpp
+
+
+
+
+
+
+
Index: Shared/newmat/newmat1.cpp
===================================================================
RCS file: Shared/newmat/newmat1.cpp
diff -N Shared/newmat/newmat1.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat1.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,199 @@
+//$$ newmat1.cpp   Matrix type functions
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,1); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************* MatrixType functions *****************************/
+
+
+// Skew needs more work <<<<<<<<<
+
+// all operations to return MatrixTypes which correspond to valid types
+// of matrices.
+// Eg: if it has the Diagonal attribute, then it must also have
+// Upper, Lower, Band, Square and Symmetric.
+
+
+MatrixType MatrixType::operator*(const MatrixType& mt) const
+{
+   REPORT
+   int a = attribute & mt.attribute & ~(Symmetric | Skew);
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::SP(const MatrixType& mt) const
+// elementwise product
+// Lower, Upper, Diag, Band if only one is
+// Symmetric, Ones, Valid (and Real) if both are
+// Need to include Lower & Upper => Diagonal
+// Will need to include both Skew => Symmetric
+{
+   REPORT
+   int a = ((attribute | mt.attribute) & ~(Symmetric + Skew + Valid + Ones))
+      | (attribute & mt.attribute);
+   if ((a & Lower) != 0  &&  (a & Upper) != 0) a |= Diagonal;
+   if ((attribute & Skew) != 0)
+   {
+      if ((mt.attribute & Symmetric) != 0) a |= Skew;  
+      if ((mt.attribute & Skew) != 0) { a &= ~Skew; a |= Symmetric; }
+   }
+   else if ((mt.attribute & Skew) != 0 && (attribute & Symmetric) != 0)
+      a |= Skew;  
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::KP(const MatrixType& mt) const
+// Kronecker product
+// Lower, Upper, Diag, Symmetric, Band, Valid if both are
+// Band if LHS is band & other is square 
+// Ones is complicated so leave this out
+{
+   REPORT
+   int a = (attribute & mt.attribute)  & ~Ones;
+   if ((attribute & Band) != 0 && (mt.attribute & Square) != 0)
+      a |= Band;
+   //int a = ((attribute & mt.attribute) | (attribute & Band)) & ~Ones;
+
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::i() const               // type of inverse
+{
+   REPORT
+   int a = attribute & ~(Band+LUDeco);
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::t() const
+// swap lower and upper attributes
+// assume Upper is in bit above Lower
+{
+   REPORT
+   int a = attribute;
+   a ^= (((a >> 1) ^ a) & Lower) * 3;
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::MultRHS() const
+{
+   REPORT
+   // remove symmetric attribute unless diagonal
+   return (attribute >= Dg) ? attribute : (attribute & ~Symmetric);
+}
+
+// this is used for deciding type of multiplication
+bool Rectangular(MatrixType a, MatrixType b, MatrixType c)
+{
+   REPORT
+   return
+      ((a.attribute | b.attribute | c.attribute)
+      & ~(MatrixType::Valid | MatrixType::Square)) == 0;
+}
+
+const char* MatrixType::Value() const
+{
+// make a string with the name of matrix with the given attributes
+   switch (attribute)
+   {
+   case Valid:                              REPORT return "Rect ";
+   case Valid+Square:                       REPORT return "Squ  ";
+   case Valid+Symmetric+Square:             REPORT return "Sym  ";
+   case Valid+Skew+Square:                  REPORT return "Skew ";
+   case Valid+Band+Square:                  REPORT return "Band ";
+   case Valid+Symmetric+Band+Square:        REPORT return "SmBnd";
+   case Valid+Upper+Square:                 REPORT return "UT   ";
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
+                                            REPORT return "Diag ";
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
+                                            REPORT return "Ident";
+   case Valid+Band+Upper+Square:            REPORT return "UpBnd";
+   case Valid+Lower+Square:                 REPORT return "LT   ";
+   case Valid+Band+Lower+Square:            REPORT return "LwBnd";
+   default:
+      REPORT
+      if (!(attribute & Valid))             return "UnSp ";
+      if (attribute & LUDeco)
+         return (attribute & Band) ?     "BndLU" : "Crout";
+                                            return "?????";
+   }
+}
+
+
+GeneralMatrix* MatrixType::New(int nr, int nc, BaseMatrix* bm) const
+{
+// make a new matrix with the given attributes
+
+   Tracer tr("New"); GeneralMatrix* gm=0;   // initialised to keep gnu happy
+   switch (attribute)
+   {
+   case Valid:
+      REPORT
+      if (nc==1) { gm = new ColumnVector(nr); break; }
+      if (nr==1) { gm = new RowVector(nc); break; }
+      gm = new Matrix(nr, nc); break;
+
+   case Valid+Square:
+      REPORT
+      if (nc!=nr) { Throw(NotSquareException()); }
+      gm = new SquareMatrix(nr); break;
+
+   case Valid+Symmetric+Square:
+      REPORT gm = new SymmetricMatrix(nr); break;
+
+   case Valid+Band+Square:
+      {
+         REPORT
+         MatrixBandWidth bw = bm->BandWidth();
+         gm = new BandMatrix(nr,bw.lower,bw.upper); break;
+      }
+
+   case Valid+Symmetric+Band+Square:
+      REPORT gm = new SymmetricBandMatrix(nr,bm->BandWidth().lower); break;
+
+   case Valid+Upper+Square:
+      REPORT gm = new UpperTriangularMatrix(nr); break;
+
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
+      REPORT gm = new DiagonalMatrix(nr); break;
+
+   case Valid+Band+Upper+Square:
+      REPORT gm = new UpperBandMatrix(nr,bm->BandWidth().upper); break;
+
+   case Valid+Lower+Square:
+      REPORT gm = new LowerTriangularMatrix(nr); break;
+
+   case Valid+Band+Lower+Square:
+      REPORT gm = new LowerBandMatrix(nr,bm->BandWidth().lower); break;
+
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
+      REPORT gm = new IdentityMatrix(nr); break;
+
+   default:
+      Throw(ProgramException("Invalid matrix type"));
+   }
+   
+   MatrixErrorNoSpace(gm); gm->Protect(); return gm;
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat2.cpp
===================================================================
RCS file: Shared/newmat/newmat2.cpp
diff -N Shared/newmat/newmat2.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat2.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,641 @@
+//$$ newmat2.cpp      Matrix row and column operations
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,2); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+//#define MONITOR(what,storage,store) { cout << what << " " << storage << " at " << (long)store << "\n"; }
+
+#define MONITOR(what,store,storage) {}
+
+/************************** Matrix Row/Col functions ************************/
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc)
+{
+   // THIS += mrc
+   REPORT
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ += *el++;
+}
+
+void MatrixRowCol::AddScaled(const MatrixRowCol& mrc, Real x)
+{
+   REPORT
+   // THIS += (mrc * x)
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ += *el++ * x;
+}
+
+void MatrixRowCol::Sub(const MatrixRowCol& mrc)
+{
+   REPORT
+   // THIS -= mrc
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ -= *el++;
+}
+
+void MatrixRowCol::Inject(const MatrixRowCol& mrc)
+// copy stored elements only
+{
+   REPORT
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* ely=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ = *ely++;
+}
+
+Real DotProd(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   REPORT                                         // not accessed
+   int f = mrc1.skip; int f2 = mrc2.skip;
+   int l = f + mrc1.storage; int l2 = f2 + mrc2.storage;
+   if (f < f2) f = f2; if (l > l2) l = l2; l -= f;
+   if (l<=0) return 0.0;
+
+   Real* el1=mrc1.data+(f-mrc1.skip); Real* el2=mrc2.data+(f-mrc2.skip);
+   Real sum = 0.0;
+   while (l--) sum += *el1++ * *el2++;
+   return sum;
+}
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 + mrc2
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip);
+   Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
+   if (f1<f2)
+   {
+      int i = f1-f; while (i--) *el++ = 0.0;
+      if (l1<=f2)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = f2-l1;     while (i--) *el++ = 0.0;
+         i = l2-f2;     while (i--) *el++ = *el2++;
+         i = l-l2;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f2-f1;    while (i--) *el++ = *el1++;
+         if (l1<=l2)
+         {
+            REPORT
+            i = l1-f2; while (i--) *el++ = *el1++ + *el2++;
+            i = l2-l1; while (i--) *el++ = *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l2-f2; while (i--) *el++ = *el1++ + *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+   else
+   {
+      int i = f2-f; while (i--) *el++ = 0.0;
+      if (l2<=f1)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l2-f2;     while (i--) *el++ = *el2++;
+         i = f1-l2;     while (i--) *el++ = 0.0;
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = l-l1;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f1-f2;    while (i--) *el++ = *el2++;
+         if (l2<=l1)
+         {
+            REPORT
+            i = l2-f1; while (i--) *el++ = *el1++ + *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l1-f1; while (i--) *el++ = *el1++ + *el2++;
+            i = l2-l1; while (i--) *el++ = *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+}
+
+void MatrixRowCol::Sub(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 - mrc2
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip);
+   Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
+   if (f1<f2)
+   {
+      int i = f1-f; while (i--) *el++ = 0.0;
+      if (l1<=f2)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = f2-l1;     while (i--) *el++ = 0.0;
+         i = l2-f2;     while (i--) *el++ = - *el2++;
+         i = l-l2;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f2-f1;    while (i--) *el++ = *el1++;
+         if (l1<=l2)
+         {
+            REPORT
+            i = l1-f2; while (i--) *el++ = *el1++ - *el2++;
+            i = l2-l1; while (i--) *el++ = - *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l2-f2; while (i--) *el++ = *el1++ - *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+   else
+   {
+      int i = f2-f; while (i--) *el++ = 0.0;
+      if (l2<=f1)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l2-f2;     while (i--) *el++ = - *el2++;
+         i = f1-l2;     while (i--) *el++ = 0.0;
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = l-l1;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f1-f2;    while (i--) *el++ = - *el2++;
+         if (l2<=l1)
+         {
+            REPORT
+            i = l2-f1; while (i--) *el++ = *el1++ - *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l1-f1; while (i--) *el++ = *el1++ - *el2++;
+            i = l2-l1; while (i--) *el++ = - *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+}
+
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc1, Real x)
+{
+   // THIS = mrc1 + x
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = x;
+       l1 = l-f;     while (l1--) *elx++ = *ely++ + x;
+       lx -= l;      while (lx--) *elx++ = x;
+}
+
+void MatrixRowCol::NegAdd(const MatrixRowCol& mrc1, Real x)
+{
+   // THIS = x - mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = x;
+       l1 = l-f;     while (l1--) *elx++ = x - *ely++;
+       lx -= l;      while (lx--) *elx++ = x;
+}
+
+void MatrixRowCol::RevSub(const MatrixRowCol& mrc1)
+{
+   // THIS = mrc - THIS
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) { *elx = - *elx; elx++; }
+       l1 = l-f;     while (l1--) { *elx = *ely++ - *elx; elx++; }
+       lx -= l;      while (lx--) { *elx = - *elx; elx++; }
+}
+
+void MatrixRowCol::ConCat(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 | mrc2
+   REPORT
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; int lx = skip + storage;
+   if (f1 < skip) { f1 = skip; if (l1 < f1) l1 = f1; }
+   if (l1 > lx) { l1 = lx; if (f1 > lx) f1 = lx; }
+
+   Real* elx = data;
+
+   int i = f1-skip;  while (i--) *elx++ =0.0;
+   i = l1-f1;
+   if (i)                       // in case f1 would take ely out of range
+      { Real* ely = mrc1.data+(f1-mrc1.skip);  while (i--) *elx++ = *ely++; }
+
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; i = mrc1.length;
+   int skipx = l1 - i; lx -= i; // addresses rel to second seg, maybe -ve
+   if (f2 < skipx) { f2 = skipx; if (l2 < f2) l2 = f2; }
+   if (l2 > lx) { l2 = lx; if (f2 > lx) f2 = lx; }
+
+   i = f2-skipx; while (i--) *elx++ = 0.0;
+   i = l2-f2;
+   if (i)                       // in case f2 would take ely out of range
+      { Real* ely = mrc2.data+(f2-mrc2.skip); while (i--) *elx++ = *ely++; }
+   lx -= l2;     while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1)
+// element by element multiply into
+{
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0;
+       l1 = l-f;     while (l1--) *elx++ *= *ely++;
+       lx -= l;      while (lx--) *elx++ = 0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+// element by element multiply
+{
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip); int i;
+   if (f1<f2) f1 = f2; if (l1>l2) l1 = l2;
+   if (l1<=f1) { REPORT i = l-f; while (i--) *el++ = 0.0; }  // disjoint
+   else
+   {
+      REPORT
+      Real* el1 = mrc1.data+(f1-mrc1.skip);
+      Real* el2 = mrc2.data+(f1-mrc2.skip);
+      i = f1-f ;    while (i--) *el++ = 0.0;
+      i = l1-f1;    while (i--) *el++ = *el1++ * *el2++;
+      i = l-l1;     while (i--) *el++ = 0.0;
+   }
+}
+
+void MatrixRowCol::KP(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+// row for Kronecker product
+{
+   int f = skip; int s = storage; Real* el = data; int i;
+
+   i = mrc1.skip * mrc2.length;
+   if (i > f)
+   {
+      i -= f; f = 0; if (i > s) { i = s; s = 0; }  else s -= i;
+      while (i--) *el++ = 0.0;
+      if (s == 0) return;
+   }
+   else f -= i;
+
+   i = mrc1.storage; Real* el1 = mrc1.data;
+   int mrc2_skip = mrc2.skip; int mrc2_storage = mrc2.storage;
+   int mrc2_length = mrc2.length;
+   int mrc2_remain = mrc2_length - mrc2_skip - mrc2_storage;
+   while (i--)
+   {
+      int j; Real* el2 = mrc2.data; Real vel1 = *el1;
+      if (f == 0 && mrc2_length <= s)
+      {
+         j = mrc2_skip; s -= j;    while (j--) *el++ = 0.0;
+         j = mrc2_storage; s -= j; while (j--) *el++ = vel1 * *el2++;
+         j = mrc2_remain; s -= j;  while (j--) *el++ = 0.0;
+      }
+      else if (f >= mrc2_length) f -= mrc2_length;
+      else
+      {
+         j = mrc2_skip;
+         if (j > f)
+         {
+            j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = 0.0;
+         }
+         else f -= j;
+
+         j = mrc2_storage;
+         if (j > f)
+         {
+            j -= f; el2 += f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = vel1 * *el2++;
+         }
+         else f -= j;
+
+         j = mrc2_remain;
+         if (j > f)
+         {
+            j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = 0.0;
+         }
+         else f -= j;
+      }
+      if (s == 0) return;
+      ++el1;
+   }
+
+   i = (mrc1.length - mrc1.skip - mrc1.storage) * mrc2.length;
+   if (i > f)
+   {
+      i -= f; if (i > s) i = s;
+      while (i--) *el++ = 0.0;
+   }
+}
+
+
+void MatrixRowCol::Copy(const MatrixRowCol& mrc1)
+{
+   // THIS = mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = 0;
+
+   if (l-f) ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::CopyCheck(const MatrixRowCol& mrc1)
+// Throw an exception if this would lead to a loss of data
+{
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Check(const MatrixRowCol& mrc1)
+// Throw an exception if +=, -=, copy etc would lead to a loss of data
+{
+   REPORT
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
+}
+
+void MatrixRowCol::Check()
+// Throw an exception if +=, -= of constant would lead to a loss of data
+// that is: check full row is present
+// may not be appropriate for symmetric matrices
+{
+   REPORT
+   if (skip!=0 || storage!=length)
+      Throw(ProgramException("Illegal Conversion"));
+}
+
+void MatrixRowCol::Negate(const MatrixRowCol& mrc1)
+{
+   // THIS = -mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = - *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, Real s)
+{
+   // THIS = mrc1 * s
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++ * s;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void DiagonalMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
+{
+   // mrc = mrc / mrc1   (elementwise)
+   REPORT
+   int f = mrc1.skip; int f0 = mrc.skip;
+   int l = f + mrc1.storage; int lx = f0 + mrc.storage;
+   if (f < f0) { f = f0; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = mrc.data; Real* eld = store+f;
+
+   int l1 = f-f0;    while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ /= *eld++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+   // Solver makes sure input and output point to same memory
+}
+
+void IdentityMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
+{
+   // mrc = mrc / mrc1   (elementwise)
+   REPORT
+   int f = mrc1.skip; int f0 = mrc.skip;
+   int l = f + mrc1.storage; int lx = f0 + mrc.storage;
+   if (f < f0) { f = f0; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = mrc.data; Real eldv = *store;
+
+   int l1 = f-f0;    while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ /= eldv;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+   // Solver makes sure input and output point to same memory
+}
+
+void MatrixRowCol::Copy(const Real*& r)
+{
+   // THIS = *r
+   REPORT
+   Real* elx = data; const Real* ely = r+skip; r += length;
+   int l = storage; while (l--) *elx++ = *ely++;
+}
+
+void MatrixRowCol::Copy(const int*& r)
+{
+   // THIS = *r
+   REPORT
+   Real* elx = data; const int* ely = r+skip; r += length;
+   int l = storage; while (l--) *elx++ = *ely++;
+}
+
+void MatrixRowCol::Copy(Real r)
+{
+   // THIS = r
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = r;
+}
+
+void MatrixRowCol::Zero()
+{
+   // THIS = 0
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = 0;
+}
+
+void MatrixRowCol::Multiply(Real r)
+{
+   // THIS *= r
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ *= r;
+}
+
+void MatrixRowCol::Add(Real r)
+{
+   // THIS += r
+   REPORT
+   Real* elx = data; int l = storage; while (l--) *elx++ += r;
+}
+
+Real MatrixRowCol::SumAbsoluteValue()
+{
+   REPORT
+   Real sum = 0.0; Real* elx = data; int l = storage;
+   while (l--) sum += fabs(*elx++);
+   return sum;
+}
+
+// max absolute value of r and elements of row/col
+// we use <= or >= in all of these so we are sure of getting
+// r reset at least once.
+Real MatrixRowCol::MaximumAbsoluteValue1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = fabs(*elx++); if (r <= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// min absolute value of r and elements of row/col
+Real MatrixRowCol::MinimumAbsoluteValue1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = fabs(*elx++); if (r >= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// max value of r and elements of row/col
+Real MatrixRowCol::Maximum1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = *elx++; if (r <= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// min value of r and elements of row/col
+Real MatrixRowCol::Minimum1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = *elx++; if (r >= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+Real MatrixRowCol::Sum()
+{
+   REPORT
+   Real sum = 0.0; Real* elx = data; int l = storage;
+   while (l--) sum += *elx++;
+   return sum;
+}
+
+void MatrixRowCol::SubRowCol(MatrixRowCol& mrc, int skip1, int l1) const
+{
+   mrc.length = l1;  int d = skip - skip1;
+   if (d<0) { mrc.skip = 0; mrc.data = data - d; }
+   else  { mrc.skip = d; mrc.data = data; }
+   d = skip + storage - skip1;
+   d = ((l1 < d) ? l1 : d) - mrc.skip;  mrc.storage = (d < 0) ? 0 : d;
+   mrc.cw = 0;
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat3.cpp
===================================================================
RCS file: Shared/newmat/newmat3.cpp
diff -N Shared/newmat/newmat3.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat3.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,844 @@
+//$$ newmat3.cpp        Matrix get and restore rows and columns
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,3); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+//#define MONITOR(what,storage,store)
+//   { cout << what << " " << storage << " at " << (long)store << "\n"; }
+
+#define MONITOR(what,store,storage) {}
+
+
+// Control bits codes for GetRow, GetCol, RestoreRow, RestoreCol
+//
+// LoadOnEntry:
+//    Load data into MatrixRow or Col dummy array under GetRow or GetCol
+// StoreOnExit:
+//    Restore data to original matrix under RestoreRow or RestoreCol
+// DirectPart:
+//    Load or restore only part directly stored; must be set with StoreOnExit
+//    Still have decide how to handle this with symmetric
+// StoreHere:
+//    used in columns only - store data at supplied storage address;
+//    used for GetCol, NextCol & RestoreCol. No need to fill out zeros
+// HaveStore:
+//    dummy array has been assigned (internal use only).
+
+// For symmetric matrices, treat columns as rows unless StoreHere is set;
+// then stick to columns as this will give better performance for doing
+// inverses
+
+// How components are used:
+
+// Use rows wherever possible in preference to columns
+
+// Columns without StoreHere are used in in-exact transpose, sum column,
+// multiply a column vector, and maybe in future access to column,
+// additional multiply functions, add transpose
+
+// Columns with StoreHere are used in exact transpose (not symmetric matrices
+// or vectors, load only)
+
+// Columns with MatrixColX (Store to full column) are used in inverse and solve
+
+// Functions required for each matrix class
+
+// GetRow(MatrixRowCol& mrc)
+// GetCol(MatrixRowCol& mrc)
+// GetCol(MatrixColX& mrc)
+// RestoreRow(MatrixRowCol& mrc)
+// RestoreCol(MatrixRowCol& mrc)
+// RestoreCol(MatrixColX& mrc)
+// NextRow(MatrixRowCol& mrc)
+// NextCol(MatrixRowCol& mrc)
+// NextCol(MatrixColX& mrc)
+
+// The Restore routines assume StoreOnExit has already been checked
+// Defaults for the Next routines are given below
+// Assume cannot have both !DirectPart && StoreHere for MatrixRowCol routines
+
+
+// Default NextRow and NextCol:
+// will work as a default but need to override NextRow for efficiency
+
+void GeneralMatrix::NextRow(MatrixRowCol& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreRow(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<nrows_value) { REPORT this->GetRow(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void GeneralMatrix::NextCol(MatrixRowCol& mrc)
+{
+   REPORT                                                // 423
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_value) { REPORT this->GetCol(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void GeneralMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT                                                // 423
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_value) { REPORT this->GetCol(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+
+// routines for matrix
+
+void Matrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=mrc.length=ncols_value;
+   mrc.data=store+mrc.rowcol*ncols_value;
+}
+
+
+void Matrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=mrc.length=nrows_value;
+   if ( ncols_value==1 && !(mrc.cw*StoreHere) )      // ColumnVector
+      { REPORT mrc.data=store; }
+   else
+   {
+      Real* ColCopy;
+      if ( !(mrc.cw*(HaveStore+StoreHere)) )
+      {
+         REPORT
+         ColCopy = new Real [nrows_value]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (MatGetCol)",nrows_value,ColCopy)
+         mrc.data = ColCopy; mrc.cw += HaveStore;
+      }
+      else { REPORT ColCopy = mrc.data; }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+mrc.rowcol; int i=nrows_value;
+         //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_value; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_value; }
+      }
+   }
+}
+
+void Matrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=nrows_value; mrc.length=nrows_value;
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT  Real* ColCopy = mrc.data;
+      Real* Mstore = store+mrc.rowcol; int i=nrows_value;
+      //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_value; }
+      if (i) for (;;)
+          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_value; }
+   }
+}
+
+void Matrix::RestoreCol(MatrixRowCol& mrc)
+{
+   // always check StoreOnExit before calling RestoreCol
+   REPORT                                   // 429
+   if (+(mrc.cw*HaveStore))
+   {
+      REPORT                                // 426
+      Real* Mstore = store+mrc.rowcol; int i=nrows_value;
+      Real* Cstore = mrc.data;
+      // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_value; }
+      if (i) for (;;)
+          { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_value; }
+   }
+}
+
+void Matrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   Real* Mstore = store+mrc.rowcol; int i=nrows_value; Real* Cstore = mrc.data;
+   // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_value; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_value; }
+}
+
+void Matrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrMat(); }  // 1808
+
+void Matrix::NextCol(MatrixRowCol& mrc)
+{
+   REPORT                                        // 632
+   if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_value)
+   {
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+mrc.rowcol; int i=nrows_value;
+         //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_value; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_value; }
+      }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void Matrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_value)
+   {
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+mrc.rowcol; int i=nrows_value;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_value; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_value; }
+      }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+// routines for diagonal matrix
+
+void DiagonalMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1;
+   mrc.data=store+mrc.skip; mrc.length=ncols_value;
+}
+
+void DiagonalMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_value;
+   if (+(mrc.cw*StoreHere))              // should not happen
+      Throw(InternalException("DiagonalMatrix::GetCol(MatrixRowCol&)"));
+   else  { REPORT mrc.data=store+mrc.skip; }
+                                                      // not accessed
+}
+
+void DiagonalMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_value;
+   mrc.data = mrc.store+mrc.skip;
+   *(mrc.data)=*(store+mrc.skip);
+}
+
+void DiagonalMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
+						      // 800
+
+void DiagonalMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
+                        // not accessed
+
+void DiagonalMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit))
+      { REPORT *(store+mrc.rowcol)=*(mrc.data); }
+   mrc.IncrDiag();
+   int t1 = +(mrc.cw*LoadOnEntry);
+   if (t1 && mrc.rowcol < ncols_value)
+      { REPORT *(mrc.data)=*(store+mrc.rowcol); }
+}
+
+// routines for upper triangular matrix
+
+void UpperTriangularMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int row = mrc.rowcol; mrc.skip=row; mrc.length=ncols_value;
+   mrc.storage=ncols_value-row; mrc.data=store+(row*(2*ncols_value-row+1))/2;
+}
+
+
+void UpperTriangularMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
+   mrc.length=nrows_value; Real* ColCopy;
+   if ( !(mrc.cw*(StoreHere+HaveStore)) )
+   {
+      REPORT                                              // not accessed
+      ColCopy = new Real [nrows_value]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (UT GetCol)",nrows_value,ColCopy)
+      mrc.data = ColCopy; mrc.cw += HaveStore;
+   }
+   else { REPORT ColCopy = mrc.data; }
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+mrc.rowcol; int j = ncols_value;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
+   }
+}
+
+void UpperTriangularMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
+   mrc.length=nrows_value;
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* ColCopy = mrc.data;
+      Real* Mstore = store+mrc.rowcol; int j = ncols_value;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
+   }
+}
+
+void UpperTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+  REPORT
+  Real* Mstore = store+mrc.rowcol; int i=mrc.rowcol+1; int j = ncols_value;
+  Real* Cstore = mrc.data;
+  // while (i--) { *Mstore = *Cstore++; Mstore += --j; }
+  if (i) for (;;)
+     { *Mstore = *Cstore++; if (!(--i)) break; Mstore += --j; }
+}
+
+void UpperTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrUT(); }
+						      // 722
+
+// routines for lower triangular matrix
+
+void LowerTriangularMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int row=mrc.rowcol; mrc.skip=0; mrc.storage=row+1; mrc.length=ncols_value;
+   mrc.data=store+(row*(row+1))/2;
+}
+
+void LowerTriangularMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_value;
+   int i=nrows_value-col; mrc.storage=i; Real* ColCopy;
+   if ( +(mrc.cw*(StoreHere+HaveStore)) )
+      { REPORT  ColCopy = mrc.data; }
+   else
+   {
+      REPORT                                            // not accessed
+      ColCopy = new Real [nrows_value]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (LT GetCol)",nrows_value,ColCopy)
+      mrc.cw += HaveStore; mrc.data = ColCopy;
+   }
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+(col*(col+3))/2;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+   }
+}
+
+void LowerTriangularMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_value;
+   int i=nrows_value-col; mrc.storage=i; mrc.data = mrc.store + col;
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT  Real* ColCopy = mrc.data;
+      Real* Mstore = store+(col*(col+3))/2;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+   }
+}
+
+void LowerTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; Real* Cstore = mrc.data;
+   Real* Mstore = store+(col*(col+3))/2; int i=nrows_value-col;
+   //while (i--) { *Mstore = *Cstore++; Mstore += ++col; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore += ++col; }
+}
+
+void LowerTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrLT(); }
+					                 //712
+
+// routines for symmetric matrix
+
+void SymmetricMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT                                                //571
+   mrc.skip=0; int row=mrc.rowcol; mrc.length=ncols_value;
+   if (+(mrc.cw*DirectPart))
+      { REPORT mrc.storage=row+1; mrc.data=store+(row*(row+1))/2; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetRow(MatrixRowCol&)"));
+      mrc.storage=ncols_value; Real* RowCopy;
+      if (!(mrc.cw*HaveStore))
+      {
+         REPORT
+         RowCopy = new Real [ncols_value]; MatrixErrorNoSpace(RowCopy);
+         MONITOR_REAL_NEW("Make (SymGetRow)",ncols_value,RowCopy)
+         mrc.cw += HaveStore; mrc.data = RowCopy;
+      }
+      else { REPORT RowCopy = mrc.data; }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT                                         // 544
+         Real* Mstore = store+(row*(row+1))/2; int i = row;
+         while (i--) *RowCopy++ = *Mstore++;
+         i = ncols_value-row;
+         // while (i--) { *RowCopy++ = *Mstore; Mstore += ++row; }
+         if (i) for (;;)
+            { *RowCopy++ = *Mstore; if (!(--i)) break; Mstore += ++row; }
+      }
+   }
+}
+
+void SymmetricMatrix::GetCol(MatrixRowCol& mrc)
+{
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
+
+   int col=mrc.rowcol; mrc.length=nrows_value;
+   REPORT
+   mrc.skip=0;
+   if (+(mrc.cw*DirectPart))    // actually get row ??
+      { REPORT mrc.storage=col+1; mrc.data=store+(col*(col+1))/2; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
+
+      mrc.storage=ncols_value; Real* ColCopy;
+      if ( +(mrc.cw*HaveStore)) { REPORT ColCopy = mrc.data; }
+      else
+      {
+         REPORT                                      // not accessed
+         ColCopy = new Real [ncols_value]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (SymGetCol)",ncols_value,ColCopy)
+         mrc.cw += HaveStore; mrc.data = ColCopy;
+      }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+(col*(col+1))/2; int i = col;
+         while (i--) *ColCopy++ = *Mstore++;
+         i = ncols_value-col;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+}
+
+void SymmetricMatrix::GetCol(MatrixColX& mrc)
+{
+   int col=mrc.rowcol; mrc.length=nrows_value;
+   if (+(mrc.cw*DirectPart))
+   {
+      REPORT
+      mrc.skip=col; int i=nrows_value-col; mrc.storage=i;
+      mrc.data = mrc.store+col;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT                           // not accessed
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+(col*(col+3))/2;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+   else
+   {
+      REPORT
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetCol(MatrixColX&)"));
+
+      mrc.skip=0; mrc.storage=ncols_value;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+(col*(col+1))/2; int i = col;
+         while (i--) *ColCopy++ = *Mstore++;
+         i = ncols_value-col;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+}
+
+// Do not need RestoreRow because we do not allow !DirectPart && StoreOnExit
+
+void SymmetricMatrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   // Really do restore column
+   int col=mrc.rowcol; Real* Cstore = mrc.data;
+   Real* Mstore = store+(col*(col+3))/2; int i = nrows_value-col;
+   // while (i--) { *Mstore = *Cstore++; Mstore+= ++col; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore+= ++col; }
+
+}
+
+// routines for row vector
+
+void RowVector::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("RowVector::GetCol(MatrixRowCol&)"));
+
+   mrc.skip=0; mrc.storage=1; mrc.length=nrows_value;
+   mrc.data = store+mrc.rowcol;
+
+}
+
+void RowVector::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=1; mrc.length=nrows_value;
+   if (mrc.cw >= LoadOnEntry)
+      { REPORT *(mrc.data) = *(store+mrc.rowcol); }
+
+}
+
+void RowVector::NextCol(MatrixRowCol& mrc)
+{ REPORT mrc.rowcol++; mrc.data++; }
+
+void RowVector::NextCol(MatrixColX& mrc)
+{
+   if (+(mrc.cw*StoreOnExit)) { REPORT *(store+mrc.rowcol)=*(mrc.data); }
+
+   mrc.rowcol++;
+   if (mrc.rowcol < ncols_value)
+   {
+      if (+(mrc.cw*LoadOnEntry)) { REPORT *(mrc.data)=*(store+mrc.rowcol); }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void RowVector::RestoreCol(MatrixColX& mrc)
+   { REPORT *(store+mrc.rowcol)=*(mrc.data); }           // not accessed
+
+
+// routines for band matrices
+
+void BandMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r = mrc.rowcol; int w = lower+1+upper; mrc.length=ncols_value;
+   int s = r-lower;
+   if (s<0) { mrc.data = store+(r*w-s); w += s; s = 0; }
+   else mrc.data = store+r*w;
+   mrc.skip = s; s += w-ncols_value; if (s>0) w -= s; mrc.storage = w;
+}
+
+// should make special versions of this for upper and lower band matrices
+
+void BandMatrix::NextRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r = ++mrc.rowcol;
+   if (r<=lower) { mrc.storage++; mrc.data += lower+upper; }
+   else  { mrc.skip++; mrc.data += lower+upper+1; }
+   if (r>=ncols_value-upper) mrc.storage--;
+}
+
+void BandMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower+upper; int w = n+1;
+   mrc.length=nrows_value; Real* ColCopy;
+   int b; int s = c-upper;
+   if (s<=0) { w += s; s = 0; b = c+lower; } else b = s*w+n;
+   mrc.skip = s; s += w-nrows_value; if (s>0) w -= s; mrc.storage = w;
+   if ( +(mrc.cw*(StoreHere+HaveStore)) )
+      { REPORT ColCopy = mrc.data; }
+   else
+   {
+      REPORT
+      ColCopy = new Real [n+1]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (BMGetCol)",n+1,ColCopy)
+      mrc.cw += HaveStore; mrc.data = ColCopy;
+   }
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+b;
+      // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
+      if (w) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
+   }
+}
+
+void BandMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower+upper; int w = n+1;
+   mrc.length=nrows_value; int b; int s = c-upper;
+   if (s<=0) { w += s; s = 0; b = c+lower; } else b = s*w+n;
+   mrc.skip = s; s += w-nrows_value; if (s>0) w -= s; mrc.storage = w;
+   mrc.data = mrc.store+mrc.skip;
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* ColCopy = mrc.data; Real* Mstore = store+b;
+      // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
+      if (w) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
+   }
+}
+
+void BandMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower+upper; int s = c-upper;
+   Real* Mstore = store + ((s<=0) ? c+lower : s*n+s+n);
+   Real* Cstore = mrc.data;
+   int w = mrc.storage;
+   // while (w--) { *Mstore = *Cstore++; Mstore += n; }
+   if (w) for (;;)
+      { *Mstore = *Cstore++; if (!(--w)) break; Mstore += n; }
+}
+
+// routines for symmetric band matrix
+
+void SymmetricBandMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r=mrc.rowcol; int s = r-lower; int w1 = lower+1; int o = r*w1;
+   mrc.length = ncols_value;
+   if (s<0) { w1 += s; o -= s; s = 0; }
+   mrc.skip = s;
+
+   if (+(mrc.cw*DirectPart))
+      { REPORT  mrc.data = store+o; mrc.storage = w1; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetRow(MatrixRowCol&)"));
+      int w = w1+lower; s += w-ncols_value; Real* RowCopy;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+      if (!(mrc.cw*HaveStore))
+      {
+         REPORT
+         RowCopy = new Real [2*lower+1]; MatrixErrorNoSpace(RowCopy);
+         MONITOR_REAL_NEW("Make (SmBGetRow)",2*lower+1,RowCopy)
+         mrc.cw += HaveStore; mrc.data = RowCopy;
+      }
+      else { REPORT  RowCopy = mrc.data; }
+
+      if (+(mrc.cw*LoadOnEntry) && ncols_value > 0)
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *RowCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower; *RowCopy++ = *Mstore; }
+      }
+   }
+}
+
+void SymmetricBandMatrix::GetCol(MatrixRowCol& mrc)
+{
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
+
+   int c=mrc.rowcol; int w1 = lower+1; mrc.length=nrows_value;
+   REPORT
+   int s = c-lower; int o = c*w1;
+   if (s<0) { w1 += s; o -= s; s = 0; }
+   mrc.skip = s;
+
+   if (+(mrc.cw*DirectPart))
+   { REPORT  mrc.data = store+o; mrc.storage = w1; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
+      int w = w1+lower; s += w-ncols_value; Real* ColCopy;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+
+      if ( +(mrc.cw*HaveStore) ) { REPORT ColCopy = mrc.data; }
+      else
+      {
+         REPORT ColCopy = new Real [2*lower+1]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (SmBGetCol)",2*lower+1,ColCopy)
+         mrc.cw += HaveStore; mrc.data = ColCopy;
+      }
+
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *ColCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower; *ColCopy++ = *Mstore; }
+      }
+   }
+}
+
+void SymmetricBandMatrix::GetCol(MatrixColX& mrc)
+{
+   int c=mrc.rowcol; int w1 = lower+1; mrc.length=nrows_value;
+   if (+(mrc.cw*DirectPart))
+   {
+      REPORT
+      int b = c*w1+lower;
+      mrc.skip = c; c += w1-nrows_value; w1 -= c; mrc.storage = w1;
+      Real* ColCopy = mrc.data = mrc.store+mrc.skip;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+b;
+         // while (w1--) { *ColCopy++ = *Mstore; Mstore += lower; }
+         if (w1) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--w1)) break; Mstore += lower; }
+      }
+   }
+   else
+   {
+      REPORT
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixColX&)"));
+      int s = c-lower; int o = c*w1;
+      if (s<0) { w1 += s; o -= s; s = 0; }
+      mrc.skip = s;
+
+      int w = w1+lower; s += w-ncols_value;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+
+      Real* ColCopy = mrc.data = mrc.store+mrc.skip;
+
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *ColCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower; *ColCopy++ = *Mstore; }
+      }
+
+   }
+}
+
+void SymmetricBandMatrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   int c = mrc.rowcol;
+   Real* Mstore = store + c*lower+c+lower;
+   Real* Cstore = mrc.data; int w = mrc.storage;
+   // while (w--) { *Mstore = *Cstore++; Mstore += lower; }
+   if (w) for (;;)
+      { *Mstore = *Cstore++; if (!(--w)) break; Mstore += lower; }
+}
+
+// routines for identity matrix
+
+void IdentityMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.data=store; mrc.length=ncols_value;
+}
+
+void IdentityMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_value;
+   if (+(mrc.cw*StoreHere))              // should not happen
+      Throw(InternalException("IdentityMatrix::GetCol(MatrixRowCol&)"));
+   else  { REPORT mrc.data=store; }
+}
+
+void IdentityMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_value;
+   mrc.data = mrc.store+mrc.skip; *(mrc.data)=*store;
+}
+
+void IdentityMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
+
+void IdentityMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
+
+void IdentityMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT *store=*(mrc.data); }
+   mrc.IncrDiag();            // must increase mrc.data so need IncrDiag
+   int t1 = +(mrc.cw*LoadOnEntry);
+   if (t1 && mrc.rowcol < ncols_value) { REPORT *(mrc.data)=*store; }
+}
+
+
+
+
+// *************************** destructors *******************************
+
+MatrixRowCol::~MatrixRowCol()
+{
+   if (+(cw*HaveStore))
+   {
+      MONITOR_REAL_DELETE("Free    (RowCol)",-1,data)  // do not know length
+      delete [] data;
+   }
+}
+
+MatrixRow::~MatrixRow() { if (+(cw*StoreOnExit)) gm->RestoreRow(*this); }
+
+MatrixCol::~MatrixCol() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
+
+MatrixColX::~MatrixColX() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat4.cpp
===================================================================
RCS file: Shared/newmat/newmat4.cpp
diff -N Shared/newmat/newmat4.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat4.cpp	23 Jul 2004 21:31:20 -0000	1.2
@@ -0,0 +1,1137 @@
+//$$ newmat4.cpp       Constructors, ReSize, basic utilities
+
+// Copyright (C) 1991,2,3,4,8,9: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,4); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+#define DO_SEARCH                   // search for LHS of = in RHS
+
+// ************************* general utilities *************************/
+
+static int tristore(int n)                    // elements in triangular matrix
+{ return (n*(n+1))/2; }
+
+
+// **************************** constructors ***************************/
+
+GeneralMatrix::GeneralMatrix()
+{ store=0; storage=0; nrows_value=0; ncols_value=0; tag=-1; }
+
+GeneralMatrix::GeneralMatrix(ArrayLengthSpecifier s)
+{
+   REPORT
+   storage=s.Value(); tag=-1;
+   if (storage)
+   {
+      store = new Real [storage]; MatrixErrorNoSpace(store);
+      MONITOR_REAL_NEW("Make (GenMatrix)",storage,store)
+   }
+   else store = 0;
+}
+
+Matrix::Matrix(int m, int n) : GeneralMatrix(m*n)
+{ REPORT nrows_value=m; ncols_value=n; }
+
+SquareMatrix::SquareMatrix(ArrayLengthSpecifier n)
+   : Matrix(n.Value(),n.Value())
+{ REPORT }
+
+SymmetricMatrix::SymmetricMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_value=n.Value(); ncols_value=n.Value(); }
+
+UpperTriangularMatrix::UpperTriangularMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_value=n.Value(); ncols_value=n.Value(); }
+
+LowerTriangularMatrix::LowerTriangularMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_value=n.Value(); ncols_value=n.Value(); }
+
+DiagonalMatrix::DiagonalMatrix(ArrayLengthSpecifier m) : GeneralMatrix(m)
+{ REPORT nrows_value=m.Value(); ncols_value=m.Value(); }
+
+Matrix::Matrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Rt);
+   GetMatrix(gmx);
+}
+
+SquareMatrix::SquareMatrix(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (ncols_value != nrows_value)
+   {
+      Tracer tr("SquareMatrix");
+      Throw(NotSquareException(*this));
+   }
+}
+
+
+SquareMatrix::SquareMatrix(const Matrix& gm)
+{
+   REPORT
+   if (gm.ncols_value != gm.nrows_value)
+   {
+      Tracer tr("SquareMatrix(Matrix)");
+      Throw(NotSquareException(gm));
+   }
+   GetMatrix(&gm);
+}
+
+
+RowVector::RowVector(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (nrows_value!=1)
+   {
+      Tracer tr("RowVector");
+      Throw(VectorException(*this));
+   }
+}
+
+ColumnVector::ColumnVector(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (ncols_value!=1)
+   {
+      Tracer tr("ColumnVector");
+      Throw(VectorException(*this));
+   }
+}
+
+SymmetricMatrix::SymmetricMatrix(const BaseMatrix& M)
+{
+   REPORT  // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Sm);
+   GetMatrix(gmx);
+}
+
+UpperTriangularMatrix::UpperTriangularMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UT);
+   GetMatrix(gmx);
+}
+
+LowerTriangularMatrix::LowerTriangularMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LT);
+   GetMatrix(gmx);
+}
+
+DiagonalMatrix::DiagonalMatrix(const BaseMatrix& M)
+{
+   REPORT //CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Dg);
+   GetMatrix(gmx);
+}
+
+IdentityMatrix::IdentityMatrix(const BaseMatrix& M)
+{
+   REPORT //CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Id);
+   GetMatrix(gmx);
+}
+
+GeneralMatrix::~GeneralMatrix()
+{
+   if (store)
+   {
+      MONITOR_REAL_DELETE("Free (GenMatrix)",storage,store)
+      delete [] store;
+   }
+}
+
+CroutMatrix::CroutMatrix(const BaseMatrix& m)
+{
+   REPORT
+   Tracer tr("CroutMatrix");
+   indx = 0;                     // in case of exception at next line
+   GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate(MatrixType::Rt);
+   GetMatrix(gm);
+   if (nrows_value!=ncols_value) { CleanUp(); Throw(NotSquareException(*gm)); }
+   d=true; sing=false;
+   indx=new int [nrows_value]; MatrixErrorNoSpace(indx);
+   MONITOR_INT_NEW("Index (CroutMat)",nrows_value,indx)
+   ludcmp();
+}
+
+CroutMatrix::~CroutMatrix()
+{
+   MONITOR_INT_DELETE("Index (CroutMat)",nrows_value,indx)
+   delete [] indx;
+}
+
+//ReturnMatrix::ReturnMatrix(GeneralMatrix& gmx)
+//{
+//   REPORT
+//   gm = gmx.Image(); gm->ReleaseAndDelete();
+//}
+
+
+GeneralMatrix::operator ReturnMatrix() const
+{
+   REPORT
+   GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
+   return ReturnMatrix(gm);
+}
+
+
+
+ReturnMatrix GeneralMatrix::ForReturn() const
+{
+   REPORT
+   GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
+   return ReturnMatrix(gm);
+}
+
+// ************ Constructors for use with NR in C++ interface ***********
+
+#ifdef SETUP_C_SUBSCRIPTS
+
+Matrix::Matrix(Real a, int m, int n) : GeneralMatrix(m * n)
+   { REPORT nrows_value=m; ncols_value=n; operator=(a); }
+   
+Matrix::Matrix(const Real* a, int m, int n) : GeneralMatrix(m * n)
+   { REPORT nrows_value=m; ncols_value=n; *this << a; }
+
+#endif
+
+
+
+// ************************** ReSize matrices ***************************/
+
+void GeneralMatrix::ReSize(int nr, int nc, int s)
+{
+   REPORT
+   if (store)
+   {
+      MONITOR_REAL_DELETE("Free (ReDimensi)",storage,store)
+      delete [] store;
+   }
+   storage=s; nrows_value=nr; ncols_value=nc; tag=-1;
+   if (s)
+   {
+      store = new Real [storage]; MatrixErrorNoSpace(store);
+      MONITOR_REAL_NEW("Make (ReDimensi)",storage,store)
+   }
+   else store = 0;
+}
+
+void Matrix::ReSize(int nr, int nc)
+{ REPORT GeneralMatrix::ReSize(nr,nc,nr*nc); }
+
+void SquareMatrix::ReSize(int n)
+{ REPORT GeneralMatrix::ReSize(n,n,n*n); }
+
+void SquareMatrix::ReSize(int nr, int nc)
+{
+   REPORT
+   Tracer tr("SquareMatrix::ReSize");
+   if (nc != nr) Throw(NotSquareException(*this));
+   GeneralMatrix::ReSize(nr,nc,nr*nc);
+}
+
+void SymmetricMatrix::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); }
+
+void UpperTriangularMatrix::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); }
+
+void LowerTriangularMatrix::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,nr,tristore(nr)); }
+
+void DiagonalMatrix::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,nr,nr); }
+
+void RowVector::ReSize(int nc)
+{ REPORT GeneralMatrix::ReSize(1,nc,nc); }
+
+void ColumnVector::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,1,nr); }
+
+void RowVector::ReSize(int nr, int nc)
+{
+   Tracer tr("RowVector::ReSize");
+   if (nr != 1) Throw(VectorException(*this));
+   REPORT GeneralMatrix::ReSize(1,nc,nc);
+}
+
+void ColumnVector::ReSize(int nr, int nc)
+{
+   Tracer tr("ColumnVector::ReSize");
+   if (nc != 1) Throw(VectorException(*this));
+   REPORT GeneralMatrix::ReSize(nr,1,nr);
+}
+
+void IdentityMatrix::ReSize(int nr)
+{ REPORT GeneralMatrix::ReSize(nr,nr,1); *store = 1; }
+
+
+void Matrix::ReSize(const GeneralMatrix& A)
+{ REPORT  ReSize(A.Nrows(), A.Ncols()); }
+
+void SquareMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SquareMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void nricMatrix::ReSize(const GeneralMatrix& A)
+{ REPORT  ReSize(A.Nrows(), A.Ncols()); }
+
+void ColumnVector::ReSize(const GeneralMatrix& A)
+{ REPORT  ReSize(A.Nrows(), A.Ncols()); }
+
+void RowVector::ReSize(const GeneralMatrix& A)
+{ REPORT  ReSize(A.Nrows(), A.Ncols()); }
+
+void SymmetricMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SymmetricMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void DiagonalMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("DiagonalMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void UpperTriangularMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("UpperTriangularMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void LowerTriangularMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("LowerTriangularMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void IdentityMatrix::ReSize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("IdentityMatrix::ReSize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   ReSize(n);
+}
+
+void GeneralMatrix::ReSize(const GeneralMatrix&)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::ReSize(GM)");
+   Throw(NotDefinedException("ReSize", "this type of matrix"));
+}
+
+void GeneralMatrix::ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix&)
+{ REPORT ReSize(A); }
+
+void GeneralMatrix::ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix&)
+{ REPORT ReSize(A); }
+
+
+// ************************* SameStorageType ******************************/
+
+// SameStorageType checks A and B have same storage type including bandwidth
+// It does not check same dimensions since we assume this is already done
+
+bool GeneralMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   REPORT
+   return Type() == A.Type();
+}
+
+
+// ******************* manipulate types, storage **************************/
+
+int GeneralMatrix::search(const BaseMatrix* s) const
+{ REPORT return (s==this) ? 1 : 0; }
+
+int GenericMatrix::search(const BaseMatrix* s) const
+{ REPORT return gm->search(s); }
+
+int MultipliedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm1->search(s) + bm2->search(s); }
+
+int ShiftedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm->search(s); }
+
+int NegatedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm->search(s); }
+
+int ReturnMatrix::search(const BaseMatrix* s) const
+{ REPORT return (s==gm) ? 1 : 0; }
+
+MatrixType Matrix::Type() const { return MatrixType::Rt; }
+MatrixType SquareMatrix::Type() const { return MatrixType::Sq; }
+MatrixType SymmetricMatrix::Type() const { return MatrixType::Sm; }
+MatrixType UpperTriangularMatrix::Type() const { return MatrixType::UT; }
+MatrixType LowerTriangularMatrix::Type() const { return MatrixType::LT; }
+MatrixType DiagonalMatrix::Type() const { return MatrixType::Dg; }
+MatrixType RowVector::Type() const { return MatrixType::RV; }
+MatrixType ColumnVector::Type() const { return MatrixType::CV; }
+MatrixType CroutMatrix::Type() const { return MatrixType::Ct; }
+MatrixType BandMatrix::Type() const { return MatrixType::BM; }
+MatrixType UpperBandMatrix::Type() const { return MatrixType::UB; }
+MatrixType LowerBandMatrix::Type() const { return MatrixType::LB; }
+MatrixType SymmetricBandMatrix::Type() const { return MatrixType::SB; }
+
+MatrixType IdentityMatrix::Type() const { return MatrixType::Id; }
+
+
+
+MatrixBandWidth BaseMatrix::BandWidth() const { REPORT return -1; }
+MatrixBandWidth DiagonalMatrix::BandWidth() const { REPORT return 0; }
+MatrixBandWidth IdentityMatrix::BandWidth() const { REPORT return 0; }
+
+MatrixBandWidth UpperTriangularMatrix::BandWidth() const
+   { REPORT return MatrixBandWidth(0,-1); }
+
+MatrixBandWidth LowerTriangularMatrix::BandWidth() const
+   { REPORT return MatrixBandWidth(-1,0); }
+
+MatrixBandWidth BandMatrix::BandWidth() const
+   { REPORT return MatrixBandWidth(lower,upper); }
+
+MatrixBandWidth GenericMatrix::BandWidth()const
+   { REPORT return gm->BandWidth(); }
+
+MatrixBandWidth AddedMatrix::BandWidth() const
+   { REPORT return gm1->BandWidth() + gm2->BandWidth(); }
+
+MatrixBandWidth SPMatrix::BandWidth() const
+   { REPORT return gm1->BandWidth().minimum(gm2->BandWidth()); }
+
+MatrixBandWidth KPMatrix::BandWidth() const
+{
+   int lower, upper;
+   MatrixBandWidth bw1 = gm1->BandWidth(), bw2 = gm2->BandWidth();
+   if (bw1.Lower() < 0)
+   {
+      if (bw2.Lower() < 0) { REPORT lower = -1; }
+      else { REPORT lower = bw2.Lower() + (gm1->Nrows() - 1) * gm2->Nrows(); }
+   }
+   else
+   {
+      if (bw2.Lower() < 0)
+         { REPORT lower = (1 + bw1.Lower()) * gm2->Nrows() - 1; }
+      else { REPORT lower = bw2.Lower() + bw1.Lower() * gm2->Nrows(); }
+   }
+   if (bw1.Upper() < 0)
+   {
+      if (bw2.Upper() < 0) { REPORT upper = -1; }
+      else { REPORT upper = bw2.Upper() + (gm1->Nrows() - 1) * gm2->Nrows(); }
+   }
+   else
+   {
+      if (bw2.Upper() < 0)
+         { REPORT upper = (1 + bw1.Upper()) * gm2->Nrows() - 1; }
+      else { REPORT upper = bw2.Upper() + bw1.Upper() * gm2->Nrows(); }
+   }
+   return MatrixBandWidth(lower, upper);
+}
+
+MatrixBandWidth MultipliedMatrix::BandWidth() const
+{ REPORT return gm1->BandWidth() * gm2->BandWidth(); }
+
+MatrixBandWidth ConcatenatedMatrix::BandWidth() const { REPORT return -1; }
+
+MatrixBandWidth SolvedMatrix::BandWidth() const
+{
+   if (+gm1->Type() & MatrixType::Diagonal)
+      { REPORT return gm2->BandWidth(); }
+   else { REPORT return -1; }
+}
+
+MatrixBandWidth ScaledMatrix::BandWidth() const
+   { REPORT return gm->BandWidth(); }
+
+MatrixBandWidth NegatedMatrix::BandWidth() const
+   { REPORT return gm->BandWidth(); }
+
+MatrixBandWidth TransposedMatrix::BandWidth() const
+   { REPORT return gm->BandWidth().t(); }
+
+MatrixBandWidth InvertedMatrix::BandWidth() const
+{
+   if (+gm->Type() & MatrixType::Diagonal)
+      { REPORT return MatrixBandWidth(0,0); }
+   else { REPORT return -1; }
+}
+
+MatrixBandWidth RowedMatrix::BandWidth() const { REPORT return -1; }
+MatrixBandWidth ColedMatrix::BandWidth() const { REPORT return -1; }
+MatrixBandWidth DiagedMatrix::BandWidth() const { REPORT return 0; }
+MatrixBandWidth MatedMatrix::BandWidth() const { REPORT return -1; }
+MatrixBandWidth ReturnMatrix::BandWidth() const
+   { REPORT return gm->BandWidth(); }
+
+MatrixBandWidth GetSubMatrix::BandWidth() const
+{
+
+   if (row_skip==col_skip && row_number==col_number)
+      { REPORT return gm->BandWidth(); }
+   else { REPORT return MatrixBandWidth(-1); }
+}
+
+// ********************** the memory managment tools **********************/
+
+//  Rules regarding tDelete, reuse, GetStore, BorrowStore
+//    All matrices processed during expression evaluation must be subject
+//    to exactly one of reuse(), tDelete(), GetStore() or BorrowStore().
+//    If reuse returns true the matrix must be reused.
+//    GetMatrix(gm) always calls gm->GetStore()
+//    gm->Evaluate obeys rules
+//    bm->Evaluate obeys rules for matrices in bm structure
+
+void GeneralMatrix::tDelete()
+{
+   if (tag<0)
+   {
+      if (tag<-1) { REPORT store = 0; delete this; return; }  // borrowed
+      else { REPORT return; }   // not a temporary matrix - leave alone
+   }
+   if (tag==1)
+   {
+      if (store)
+      {
+         REPORT  MONITOR_REAL_DELETE("Free   (tDelete)",storage,store)
+         delete [] store;
+      }
+      MiniCleanUp(); return;                           // CleanUp
+   }
+   if (tag==0) { REPORT delete this; return; }
+
+   REPORT tag--; return;
+}
+
+static void BlockCopy(int n, Real* from, Real* to)
+{
+   REPORT
+   int i = (n >> 3);
+   while (i--)
+   {
+      *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
+      *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
+   }
+   i = n & 7; while (i--) *to++ = *from++;
+}
+
+bool GeneralMatrix::reuse()
+{
+   if (tag < -1)                 // borrowed storage
+   {
+      if (storage)
+      {
+         REPORT
+         Real* s = new Real [storage]; MatrixErrorNoSpace(s);
+         MONITOR_REAL_NEW("Make     (reuse)",storage,s)
+         BlockCopy(storage, store, s); store = s;
+      }
+      else { REPORT MiniCleanUp(); }                // CleanUp
+      tag = 0; return true;
+   }
+   if (tag < 0 ) { REPORT return false; }
+   if (tag <= 1 )  { REPORT return true; }
+   REPORT tag--; return false;
+}
+
+Real* GeneralMatrix::GetStore()
+{
+   if (tag<0 || tag>1)
+   {
+      Real* s;
+      if (storage)
+      {
+         s = new Real [storage]; MatrixErrorNoSpace(s);
+         MONITOR_REAL_NEW("Make  (GetStore)",storage,s)
+         BlockCopy(storage, store, s);
+      }
+      else s = 0;
+      if (tag > 1) { REPORT tag--; }
+      else if (tag < -1) { REPORT store = 0; delete this; } // borrowed store
+      else { REPORT }
+      return s;
+   }
+   Real* s = store;                             // CleanUp - done later
+   if (tag==0) { REPORT store = 0; delete this; }
+   else { REPORT  MiniCleanUp(); }
+   return s;
+}
+
+void GeneralMatrix::GetMatrix(const GeneralMatrix* gmx)
+{
+   REPORT  tag=-1; nrows_value=gmx->Nrows(); ncols_value=gmx->Ncols();
+   storage=gmx->storage; SetParameters(gmx);
+   store=((GeneralMatrix*)gmx)->GetStore();
+}
+
+GeneralMatrix* GeneralMatrix::BorrowStore(GeneralMatrix* gmx, MatrixType mt)
+// Copy storage of *this to storage of *gmx. Then convert to type mt.
+// If mt == 0 just let *gmx point to storage of *this if tag==-1.
+{
+   if (!mt)
+   {
+      if (tag == -1) { REPORT gmx->tag = -2; gmx->store = store; }
+      else { REPORT gmx->tag = 0; gmx->store = GetStore(); }
+   }
+   else if (Compare(gmx->Type(),mt))
+   { REPORT  gmx->tag = 0; gmx->store = GetStore(); }
+   else
+   {
+      REPORT gmx->tag = -2; gmx->store = store;
+      gmx = gmx->Evaluate(mt); gmx->tag = 0; tDelete();
+   }
+
+   return gmx;
+}
+
+void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt)
+// Count number of references to this in X.
+// If zero delete storage in this;
+// otherwise tag this to show when storage can be deleted
+// evaluate X and copy to this
+{
+#ifdef DO_SEARCH
+   int counter=X.search(this);
+   if (counter==0)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+   }
+   else { REPORT Release(counter); }
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this) { REPORT GetMatrix(gmx); }
+   else { REPORT }
+   Protect();
+#else
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+      GetMatrix(gmx);
+   }
+   else { REPORT }
+   Protect();
+#endif
+}
+
+// version with no conversion
+void GeneralMatrix::Eq(const GeneralMatrix& X)
+{
+   GeneralMatrix* gmx = (GeneralMatrix*)&X;
+   if (gmx!=this)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+      GetMatrix(gmx);
+   }
+   else { REPORT }
+   Protect();
+}
+
+// version to work with operator<<
+void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt, bool ldok)
+{
+   REPORT
+   if (ldok) mt.SetDataLossOK();
+   Eq(X, mt);
+}
+
+void GeneralMatrix::Eq2(const BaseMatrix& X, MatrixType mt)
+// a cut down version of Eq for use with += etc.
+// we know BaseMatrix points to two GeneralMatrix objects,
+// the first being this (may be the same).
+// we know tag has been set correctly in each.
+{
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this) { REPORT GetMatrix(gmx); }  // simplify GetMatrix ?
+   else { REPORT }
+   Protect();
+}
+
+void GeneralMatrix::Inject(const GeneralMatrix& X)
+// copy stored values of X; otherwise leave els of *this unchanged
+{
+   REPORT
+   Tracer tr("Inject");
+   if (nrows_value != X.nrows_value || ncols_value != X.ncols_value)
+      Throw(IncompatibleDimensionsException());
+   MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
+   MatrixRow mrx(this, LoadOnEntry+StoreOnExit+DirectPart);
+   int i=nrows_value;
+   while (i--) { mrx.Inject(mr); mrx.Next(); mr.Next(); }
+}
+
+// ************* checking for data loss during conversion *******************/
+
+bool Compare(const MatrixType& source, MatrixType& destination)
+{
+   if (!destination) { destination=source; return true; }
+   if (destination==source) return true;
+   if (!destination.DataLossOK && !(destination>=source))
+      Throw(ProgramException("Illegal Conversion", source, destination));
+   return false;
+}
+
+// ************* Make a copy of a matrix on the heap *********************/
+
+GeneralMatrix* Matrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new Matrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SquareMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SquareMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SymmetricMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SymmetricMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* UpperTriangularMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new UpperTriangularMatrix(*this);
+   MatrixErrorNoSpace(gm); return gm;
+}
+
+GeneralMatrix* LowerTriangularMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new LowerTriangularMatrix(*this);
+   MatrixErrorNoSpace(gm); return gm;
+}
+
+GeneralMatrix* DiagonalMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new DiagonalMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* RowVector::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new RowVector(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* ColumnVector::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new ColumnVector(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* BandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new BandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* UpperBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new UpperBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* LowerBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new LowerBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SymmetricBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SymmetricBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* nricMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new nricMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* IdentityMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new IdentityMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* GeneralMatrix::Image() const
+{
+   bool dummy = true;
+   if (dummy)                                   // get rid of warning message
+      Throw(InternalException("Cannot apply Image to this matrix type"));
+   return 0;
+}
+
+
+// *********************** nricMatrix routines *****************************/
+
+void nricMatrix::MakeRowPointer()
+{
+   REPORT
+   if (nrows_value > 0)
+   {
+      row_pointer = new Real* [nrows_value]; MatrixErrorNoSpace(row_pointer);
+      Real* s = Store() - 1; int i = nrows_value; Real** rp = row_pointer;
+      if (i) for (;;) { *rp++ = s; if (!(--i)) break; s+=ncols_value; }
+   }
+   else row_pointer = 0;
+}
+
+void nricMatrix::DeleteRowPointer()
+   { REPORT if (nrows_value) delete [] row_pointer; }
+
+void GeneralMatrix::CheckStore() const
+{
+   REPORT
+   if (!store)
+      Throw(ProgramException("NRIC accessing matrix with unset dimensions"));
+}
+
+
+// *************************** CleanUp routines *****************************/
+
+void GeneralMatrix::CleanUp()
+{
+   // set matrix dimensions to zero, delete storage
+   REPORT
+   if (store && storage)
+   {
+      MONITOR_REAL_DELETE("Free (CleanUp)    ",storage,store)
+      REPORT delete [] store;
+   }
+   store=0; storage=0; nrows_value=0; ncols_value=0; tag = -1;
+}
+
+void nricMatrix::CleanUp()
+   { REPORT DeleteRowPointer(); GeneralMatrix::CleanUp(); }
+
+void nricMatrix::MiniCleanUp()
+   { REPORT DeleteRowPointer(); GeneralMatrix::MiniCleanUp(); }
+
+void RowVector::CleanUp()
+   { REPORT GeneralMatrix::CleanUp(); nrows_value=1; }
+
+void ColumnVector::CleanUp()
+   { REPORT GeneralMatrix::CleanUp(); ncols_value=1; }
+
+void CroutMatrix::CleanUp()
+{
+   REPORT
+   if (nrows_value) delete [] indx;
+   GeneralMatrix::CleanUp();
+}
+
+void CroutMatrix::MiniCleanUp()
+{
+   REPORT
+   if (nrows_value) delete [] indx;
+   GeneralMatrix::MiniCleanUp();
+}
+
+void BandLUMatrix::CleanUp()
+{
+   REPORT
+   if (nrows_value) delete [] indx;
+   if (storage2) delete [] store2;
+   GeneralMatrix::CleanUp();
+}
+
+void BandLUMatrix::MiniCleanUp()
+{
+   REPORT
+   if (nrows_value) delete [] indx;
+   if (storage2) delete [] store2;
+   GeneralMatrix::MiniCleanUp();
+}
+
+// ************************ simple integer array class ***********************
+
+// construct a new array of length xn. Check that xn is non-negative and
+// that space is available
+
+SimpleIntArray::SimpleIntArray(int xn) : n(xn)
+{
+   if (n < 0) Throw(Logic_error("invalid array length"));
+   else if (n == 0) { REPORT  a = 0; }
+   else { REPORT  a = new int [n]; if (!a) Throw(Bad_alloc()); }
+}
+
+// destroy an array - return its space to memory
+
+SimpleIntArray::~SimpleIntArray() { REPORT  if (a) delete [] a; }
+
+// access an element of an array; return a "reference" so elements
+// can be modified.
+// check index is within range
+// in this array class the index runs from 0 to n-1
+
+int& SimpleIntArray::operator[](int i)
+{
+   REPORT
+   if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
+   return a[i];
+}
+
+// same thing again but for arrays declared constant so we can't
+// modify its elements
+
+int SimpleIntArray::operator[](int i) const
+{
+   REPORT
+   if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
+   return a[i];
+}
+
+// set all the elements equal to a given value
+
+void SimpleIntArray::operator=(int ai)
+   { REPORT  for (int i = 0; i < n; i++) a[i] = ai; }
+
+// set the elements equal to those of another array.
+// now allow length to be changed
+
+void SimpleIntArray::operator=(const SimpleIntArray& b)
+{
+   REPORT
+   if (b.n != n) ReSize(b.n);
+   for (int i = 0; i < n; i++) a[i] = b.a[i];
+}
+
+// construct a new array equal to an existing array
+// check that space is available
+
+SimpleIntArray::SimpleIntArray(const SimpleIntArray& b) : Janitor(), n(b.n)
+{
+   if (n == 0) { REPORT  a = 0; }
+   else
+   {
+      REPORT
+      a = new int [n]; if (!a) Throw(Bad_alloc());
+      for (int i = 0; i < n; i++) a[i] = b.a[i];
+   }
+}
+
+// change the size of an array; optionally copy data from old array to
+// new array
+
+void SimpleIntArray::ReSize(int n1, bool keep)
+{
+   if (n1 == n) { REPORT  return; }
+   else if (n1 == 0) { REPORT  n = 0; delete [] a; a = 0; }
+   else if (n == 0)
+      { REPORT  a = new int [n1]; if (!a) Throw(Bad_alloc()); n = n1; }
+   else
+   {
+      int* a1 = a;
+      if (keep)
+      {
+         REPORT
+         a = new int [n1]; if (!a) Throw(Bad_alloc());
+         if (n > n1) n = n1;
+         for (int i = 0; i < n; i++) a[i] = a1[i];
+         n = n1; delete [] a1;
+      }
+      else
+      {
+         REPORT  n = n1; delete [] a1;
+         a = new int [n]; if (!a) Throw(Bad_alloc());
+      }
+   }
+}
+
+//************************** swap values ********************************
+
+// swap values
+
+void GeneralMatrix::swap(GeneralMatrix& gm)
+{
+   REPORT
+   int t;
+   t = tag; tag = gm.tag; gm.tag = t;
+   t = nrows_value; nrows_value = gm.nrows_value; gm.nrows_value = t;
+   t = ncols_value; ncols_value = gm.ncols_value; gm.ncols_value = t;
+   t = storage; storage = gm.storage; gm.storage = t;
+   Real* s = store; store = gm.store; gm.store = s;
+}
+   
+void nricMatrix::swap(nricMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   Real** rp = row_pointer; row_pointer = gm.row_pointer; gm.row_pointer = rp;
+}
+
+void CroutMatrix::swap(CroutMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int* i = indx; indx = gm.indx; gm.indx = i;
+   bool b;
+   b = d; d = gm.d; gm.d = b;
+   b = sing; sing = gm.sing; gm.sing = b;
+}
+
+void BandMatrix::swap(BandMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int i;
+   i = lower; lower = gm.lower; gm.lower = i;
+   i = upper; upper = gm.upper; gm.upper = i;
+}
+
+void SymmetricBandMatrix::swap(SymmetricBandMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int i;
+   i = lower; lower = gm.lower; gm.lower = i;
+}
+
+void BandLUMatrix::swap(BandLUMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int* i = indx; indx = gm.indx; gm.indx = i;
+   bool b;
+   b = d; d = gm.d; gm.d = b;
+   b = sing; sing = gm.sing; gm.sing = b;
+   int m;
+   m = storage2; storage2 = gm.storage2; gm.storage2 = m;
+   m = m1; m1 = gm.m1; gm.m1 = m;
+   m = m2; m2 = gm.m2; gm.m2 = m;
+   Real* s = store2; store2 = gm.store2; gm.store2 = s;
+}
+
+void GenericMatrix::swap(GenericMatrix& x)
+{
+   REPORT
+   GeneralMatrix* tgm = gm; gm = x.gm; x.gm = tgm;
+}
+
+// ********************** C subscript classes ****************************
+
+RealStarStar::RealStarStar(Matrix& A)
+{
+   REPORT
+   Tracer tr("RealStarStar");
+   int n = A.ncols();
+   int m = A.nrows();
+   a = new Real*[m];
+   MatrixErrorNoSpace(a);
+   Real* d = A.data();
+   for (int i = 0; i < m; ++i) a[i] = d + i * n;
+} 
+
+ConstRealStarStar::ConstRealStarStar(const Matrix& A)
+{
+   REPORT
+   Tracer tr("ConstRealStarStar");
+   int n = A.ncols();
+   int m = A.nrows();
+   a = new const Real*[m];
+   MatrixErrorNoSpace(a);
+   const Real* d = A.data();
+   for (int i = 0; i < m; ++i) a[i] = d + i * n;
+} 
+
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat5.cpp
===================================================================
RCS file: Shared/newmat/newmat5.cpp
diff -N Shared/newmat/newmat5.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat5.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,485 @@
+//$$ newmat5.cpp         Transpose, evaluate etc
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,5); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************ carry out operations ******************************/
+
+
+GeneralMatrix* GeneralMatrix::Transpose(TransposedMatrix* tm, MatrixType mt)
+{
+   GeneralMatrix* gm1;
+
+   if (Compare(Type().t(),mt))
+   {
+      REPORT
+      gm1 = mt.New(ncols_value,nrows_value,tm);
+      for (int i=0; i<ncols_value; i++)
+      {
+         MatrixRow mr(gm1, StoreOnExit+DirectPart, i);
+         MatrixCol mc(this, mr.Data(), LoadOnEntry, i);
+      }
+   }
+   else
+   {
+      REPORT
+      gm1 = mt.New(ncols_value,nrows_value,tm);
+      MatrixRow mr(this, LoadOnEntry);
+      MatrixCol mc(gm1, StoreOnExit+DirectPart);
+      int i = nrows_value;
+      while (i--) { mc.Copy(mr); mr.Next(); mc.Next(); }
+   }
+   tDelete(); gm1->ReleaseAndDelete(); return gm1;
+}
+
+GeneralMatrix* SymmetricMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT  return Evaluate(mt); }
+
+
+GeneralMatrix* DiagonalMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT return Evaluate(mt); }
+
+GeneralMatrix* ColumnVector::Transpose(TransposedMatrix*, MatrixType mt)
+{
+   REPORT
+   GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
+   gmx->nrows_value = 1; gmx->ncols_value = gmx->storage = storage;
+   return BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* RowVector::Transpose(TransposedMatrix*, MatrixType mt)
+{
+   REPORT
+   GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
+   gmx->ncols_value = 1; gmx->nrows_value = gmx->storage = storage;
+   return BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* IdentityMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT return Evaluate(mt); }
+
+GeneralMatrix* GeneralMatrix::Evaluate(MatrixType mt)
+{
+   if (Compare(this->Type(),mt)) { REPORT return this; }
+   REPORT
+   GeneralMatrix* gmx = mt.New(nrows_value,ncols_value,this);
+   MatrixRow mr(this, LoadOnEntry);
+   MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+   int i=nrows_value;
+   while (i--) { mrx.Copy(mr); mrx.Next(); mr.Next(); }
+   tDelete(); gmx->ReleaseAndDelete(); return gmx;
+}
+
+GeneralMatrix* GenericMatrix::Evaluate(MatrixType mt)
+   { REPORT  return gm->Evaluate(mt); }
+
+GeneralMatrix* ShiftedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   Compare(gm->Type().AddEqualEl(),mt);
+   if (!(mt==gm->Type()))
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Add(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+   else if (gm->reuse())
+   {
+      REPORT gm->Add(f);
+      return gm;
+   }
+   else
+   {
+      REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
+      gmy->ReleaseAndDelete(); gmy->Add(gm,f);
+      return gmy;
+   }
+}
+
+GeneralMatrix* NegShiftedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   Compare(gm->Type().AddEqualEl(),mt);
+   if (!(mt==gm->Type()))
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.NegAdd(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+   else if (gm->reuse())
+   {
+      REPORT gm->NegAdd(f);
+      return gm;
+   }
+   else
+   {
+      REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
+      gmy->ReleaseAndDelete(); gmy->NegAdd(gm,f);
+      return gmy;
+   }
+}
+
+GeneralMatrix* ScaledMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   if (Compare(gm->Type(),mt))
+   {
+      if (gm->reuse())
+      {
+         REPORT gm->Multiply(f);
+         return gm;
+      }
+      else
+      {
+         REPORT GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
+         gmx->ReleaseAndDelete(); gmx->Multiply(gm,f);
+         return gmx;
+      }
+   }
+   else
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Multiply(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+}
+
+GeneralMatrix* NegatedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   if (Compare(gm->Type(),mt))
+   {
+      if (gm->reuse())
+      {
+         REPORT gm->Negate();
+         return gm;
+      }
+      else
+      {
+         REPORT
+         GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
+         gmx->ReleaseAndDelete(); gmx->Negate(gm);
+         return gmx;
+      }
+   }
+   else
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Negate(mr); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+}
+
+GeneralMatrix* ReversedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate(); GeneralMatrix* gmx;
+
+   if ((gm->Type()).IsBand() && ! (gm->Type()).IsDiagonal())
+   {
+      gm->tDelete();
+      Throw(NotDefinedException("Reverse", "band matrices"));
+   }
+
+   if (gm->reuse()) { REPORT gm->ReverseElements(); gmx = gm; }
+   else
+   {
+      REPORT
+      gmx = gm->Type().New(gm->Nrows(), gm->Ncols(), this);
+      gmx->ReverseElements(gm); gmx->ReleaseAndDelete();
+   }
+   return gmx->Evaluate(mt); // target matrix is different type?
+
+}
+
+GeneralMatrix* TransposedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   Compare(gm->Type().t(),mt);
+   GeneralMatrix* gmx=gm->Transpose(this, mt);
+   return gmx;
+}
+
+GeneralMatrix* RowedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
+   gmx->nrows_value = 1; gmx->ncols_value = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* ColedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
+   gmx->ncols_value = 1; gmx->nrows_value = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* DiagedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new DiagonalMatrix; MatrixErrorNoSpace(gmx);
+   gmx->nrows_value = gmx->ncols_value = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* MatedMatrix::Evaluate(MatrixType mt)
+{
+   Tracer tr("MatedMatrix::Evaluate");
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new Matrix; MatrixErrorNoSpace(gmx);
+   gmx->nrows_value = nr; gmx->ncols_value = nc; gmx->storage = gm->storage;
+   if (nr*nc != gmx->storage)
+      Throw(IncompatibleDimensionsException());
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* GetSubMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   Tracer tr("SubMatrix(evaluate)");
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   if (row_number < 0) row_number = gm->Nrows();
+   if (col_number < 0) col_number = gm->Ncols();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+   {
+      gm->tDelete();
+      Throw(SubMatrixDimensionException());
+   }
+   if (IsSym) Compare(gm->Type().ssub(), mt);
+   else Compare(gm->Type().sub(), mt);
+   GeneralMatrix* gmx = mt.New(row_number, col_number, this);
+   int i = row_number;
+   MatrixRow mr(gm, LoadOnEntry, row_skip); 
+   MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+   MatrixRowCol sub;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      mrx.Copy(sub); mrx.Next(); mr.Next();
+   }
+   gmx->ReleaseAndDelete(); gm->tDelete();
+   return gmx;
+}
+
+
+GeneralMatrix* ReturnMatrix::Evaluate(MatrixType mt)
+{
+   return gm->Evaluate(mt);
+}
+
+
+void GeneralMatrix::Add(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; }
+   i = storage & 3; while (i--) *s++ = *s1++ + f;
+}
+   
+void GeneralMatrix::Add(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--) { *s++ += f; *s++ += f; *s++ += f; *s++ += f; }
+   i = storage & 3; while (i--) *s++ += f;
+}
+   
+void GeneralMatrix::NegAdd(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; }
+   i = storage & 3; while (i--) *s++ = f - *s1++;
+}
+   
+void GeneralMatrix::NegAdd(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--)
+   {
+      *s = f - *s; s++; *s = f - *s; s++;
+      *s = f - *s; s++; *s = f - *s; s++;
+   }
+   i = storage & 3; while (i--)  { *s = f - *s; s++; }
+}
+   
+void GeneralMatrix::Negate(GeneralMatrix* gm1)
+{
+   // change sign of elements
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); }
+   i = storage & 3; while(i--) *s++ = -(*s1++);
+}
+   
+void GeneralMatrix::Negate()
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; }
+   i = storage & 3; while(i--) { *s = -(*s); s++; }
+}
+   
+void GeneralMatrix::Multiply(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store;  int i=(storage >> 2);
+   while (i--)
+   { *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; }
+   i = storage & 3; while (i--) *s++ = *s1++ * f;
+}
+   
+void GeneralMatrix::Multiply(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--) { *s++ *= f; *s++ *= f; *s++ *= f; *s++ *= f; }
+   i = storage & 3; while (i--) *s++ *= f;
+}
+   
+
+/************************ MatrixInput routines ****************************/
+
+// int MatrixInput::n;          // number values still to be read
+// Real* MatrixInput::r;        // pointer to next location to be read to
+
+MatrixInput MatrixInput::operator<<(Real f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   if (n<=0) Throw(ProgramException("List of values too long"));
+   *r = f; int n1 = n-1; n=0;   // n=0 so we won't trigger exception
+   return MatrixInput(n1, r+1);
+}
+
+
+MatrixInput GeneralMatrix::operator<<(Real f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   int n = Storage();
+   if (n<=0) Throw(ProgramException("Loading data to zero length matrix"));
+   Real* r; r = Store(); *r = f; n--;
+   return MatrixInput(n, r+1);
+}
+
+MatrixInput GetSubMatrix::operator<<(Real f)
+{
+   REPORT
+   Tracer et("MatrixInput (GetSubMatrix)");
+   SetUpLHS();
+   if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols())
+   {
+      Throw(ProgramException("MatrixInput requires complete rows"));
+   }
+   MatrixRow mr(gm, DirectPart, row_skip);  // to pick up location and length
+   int n = mr.Storage();
+   if (n<=0)
+   {
+      Throw(ProgramException("Loading data to zero length row"));
+   }
+   Real* r; r = mr.Data(); *r = f; n--;
+   if (+(mr.cw*HaveStore))
+   {
+      Throw(ProgramException("Fails with this matrix type"));
+   }
+   return MatrixInput(n, r+1);
+}
+
+MatrixInput::~MatrixInput()
+{
+   REPORT
+   Tracer et("MatrixInput");
+   if (n!=0) Throw(ProgramException("A list of values was too short"));
+}
+
+MatrixInput BandMatrix::operator<<(Real)
+{
+   Tracer et("MatrixInput");
+   bool dummy = true;
+   if (dummy)                                   // get rid of warning message
+      Throw(ProgramException("Cannot use list read with a BandMatrix"));
+   return MatrixInput(0, 0);
+}
+
+void BandMatrix::operator<<(const Real*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void BandMatrix::operator<<(const int*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void SymmetricBandMatrix::operator<<(const Real*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void SymmetricBandMatrix::operator<<(const int*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+// ************************* Reverse order of elements ***********************
+
+void GeneralMatrix::ReverseElements(GeneralMatrix* gm)
+{
+   // reversing into a new matrix
+   REPORT
+   int n = Storage(); Real* rx = Store() + n; Real* x = gm->Store();
+   while (n--) *(--rx) = *(x++);
+}
+
+void GeneralMatrix::ReverseElements()
+{
+   // reversing in place
+   REPORT
+   int n = Storage(); Real* x = Store(); Real* rx = x + n;
+   n /= 2;
+   while (n--) { Real t = *(--rx); *rx = *x; *(x++) = t; }
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat6.cpp
===================================================================
RCS file: Shared/newmat/newmat6.cpp
diff -N Shared/newmat/newmat6.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat6.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,884 @@
+//$$ newmat6.cpp            Operators, element access, submatrices
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,6); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/*************************** general utilities *************************/
+
+static int tristore(int n)                      // els in triangular matrix
+{ return (n*(n+1))/2; }
+
+
+/****************************** operators *******************************/
+
+Real& Matrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_value+n-1];
+}
+
+Real& SymmetricMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || n<=0 || m>nrows_value || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   if (m>=n) return store[tristore(m-1)+n-1];
+   else return store[tristore(n-1)+m-1];
+}
+
+Real& UpperTriangularMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || n<m || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_value+n-1-tristore(m-1)];
+}
+
+Real& LowerTriangularMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (n<=0 || m<n || m>nrows_value)
+      Throw(IndexException(m,n,*this));
+   return store[tristore(m-1)+n-1];
+}
+
+Real& DiagonalMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (n<=0 || m!=n || m>nrows_value || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[n-1];
+}
+
+Real& DiagonalMatrix::operator()(int m)
+{
+   REPORT
+   if (m<=0 || m>nrows_value) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real& ColumnVector::operator()(int m)
+{
+   REPORT
+   if (m<=0 || m> nrows_value) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real& RowVector::operator()(int n)
+{
+   REPORT
+   if (n<=0 || n> ncols_value) Throw(IndexException(n,*this));
+   return store[n-1];
+}
+
+Real& BandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = upper+lower+1; int i = lower+n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& UpperBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = upper+1; int i = n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& LowerBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = lower+1; int i = lower+n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& SymmetricBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = lower+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower+n-m;
+      if ( m>nrows_value || n<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(m-1)+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower+m-n;
+      if ( n>nrows_value || m<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(n-1)+i];
+   }
+}
+
+
+Real Matrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_value+n-1];
+}
+
+Real SymmetricMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || n<=0 || m>nrows_value || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   if (m>=n) return store[tristore(m-1)+n-1];
+   else return store[tristore(n-1)+m-1];
+}
+
+Real UpperTriangularMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || n<m || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_value+n-1-tristore(m-1)];
+}
+
+Real LowerTriangularMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (n<=0 || m<n || m>nrows_value)
+      Throw(IndexException(m,n,*this));
+   return store[tristore(m-1)+n-1];
+}
+
+Real DiagonalMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (n<=0 || m!=n || m>nrows_value || n>ncols_value)
+      Throw(IndexException(m,n,*this));
+   return store[n-1];
+}
+
+Real DiagonalMatrix::operator()(int m) const
+{
+   REPORT
+   if (m<=0 || m>nrows_value) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real ColumnVector::operator()(int m) const
+{
+   REPORT
+   if (m<=0 || m> nrows_value) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real RowVector::operator()(int n) const
+{
+   REPORT
+   if (n<=0 || n> ncols_value) Throw(IndexException(n,*this));
+   return store[n-1];
+}
+
+Real BandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = upper+lower+1; int i = lower+n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real UpperBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = upper+1; int i = n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real LowerBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = lower+1; int i = lower+n-m;
+   if (m<=0 || m>nrows_value || n<=0 || n>ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real SymmetricBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = lower+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower+n-m;
+      if ( m>nrows_value || n<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(m-1)+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower+m-n;
+      if ( n>nrows_value || m<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(n-1)+i];
+   }
+}
+
+
+Real BaseMatrix::AsScalar() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+
+   if (gm->nrows_value!=1 || gm->ncols_value!=1)
+   {
+      Tracer tr("AsScalar");
+      Try
+         { Throw(ProgramException("Cannot convert to scalar", *gm)); }
+      CatchAll { gm->tDelete(); ReThrow; }
+   }
+
+   Real x = *(gm->store); gm->tDelete(); return x;
+}
+
+
+AddedMatrix BaseMatrix::operator+(const BaseMatrix& bm) const
+{ REPORT return AddedMatrix(this, &bm); }
+
+SPMatrix SP(const BaseMatrix& bm1,const BaseMatrix& bm2)
+{ REPORT return SPMatrix(&bm1, &bm2); }
+
+KPMatrix KP(const BaseMatrix& bm1,const BaseMatrix& bm2)
+{ REPORT return KPMatrix(&bm1, &bm2); }
+
+MultipliedMatrix BaseMatrix::operator*(const BaseMatrix& bm) const
+{ REPORT return MultipliedMatrix(this, &bm); }
+
+ConcatenatedMatrix BaseMatrix::operator|(const BaseMatrix& bm) const
+{ REPORT return ConcatenatedMatrix(this, &bm); }
+
+StackedMatrix BaseMatrix::operator&(const BaseMatrix& bm) const
+{ REPORT return StackedMatrix(this, &bm); }
+
+SolvedMatrix InvertedMatrix::operator*(const BaseMatrix& bmx) const
+{ REPORT return SolvedMatrix(bm, &bmx); }
+
+SubtractedMatrix BaseMatrix::operator-(const BaseMatrix& bm) const
+{ REPORT return SubtractedMatrix(this, &bm); }
+
+ShiftedMatrix BaseMatrix::operator+(Real f) const
+{ REPORT return ShiftedMatrix(this, f); }
+
+ShiftedMatrix operator+(Real f, const BaseMatrix& BM)
+{ REPORT return ShiftedMatrix(&BM, f); }
+
+NegShiftedMatrix operator-(Real f, const BaseMatrix& bm)
+{ REPORT return NegShiftedMatrix(f, &bm); }
+
+ScaledMatrix BaseMatrix::operator*(Real f) const
+{ REPORT return ScaledMatrix(this, f); }
+
+ScaledMatrix BaseMatrix::operator/(Real f) const
+{ REPORT return ScaledMatrix(this, 1.0/f); }
+
+ScaledMatrix operator*(Real f, const BaseMatrix& BM)
+{ REPORT return ScaledMatrix(&BM, f); }
+
+ShiftedMatrix BaseMatrix::operator-(Real f) const
+{ REPORT return ShiftedMatrix(this, -f); }
+
+TransposedMatrix BaseMatrix::t() const
+{ REPORT return TransposedMatrix(this); }
+
+NegatedMatrix BaseMatrix::operator-() const
+{ REPORT return NegatedMatrix(this); }
+
+ReversedMatrix BaseMatrix::Reverse() const
+{ REPORT return ReversedMatrix(this); }
+
+InvertedMatrix BaseMatrix::i() const
+{ REPORT return InvertedMatrix(this); }
+
+
+RowedMatrix BaseMatrix::AsRow() const
+{ REPORT return RowedMatrix(this); }
+
+ColedMatrix BaseMatrix::AsColumn() const
+{ REPORT return ColedMatrix(this); }
+
+DiagedMatrix BaseMatrix::AsDiagonal() const
+{ REPORT return DiagedMatrix(this); }
+
+MatedMatrix BaseMatrix::AsMatrix(int nrx, int ncx) const
+{ REPORT return MatedMatrix(this,nrx,ncx); }
+
+
+void GeneralMatrix::operator=(Real f)
+{ REPORT int i=storage; Real* s=store; while (i--) { *s++ = f; } }
+
+void Matrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Rt);
+} 
+
+void SquareMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Rt);
+   if (nrows_value != ncols_value)
+      { Tracer tr("SquareMatrix(=)"); Throw(NotSquareException(*this)); }
+}
+
+void SquareMatrix::operator=(const Matrix& m)
+{
+   REPORT
+   if (m.nrows_value != m.ncols_value)
+      { Tracer tr("SquareMatrix(=Matrix)"); Throw(NotSquareException(*this)); }
+   Eq(m);
+}
+
+void RowVector::operator=(const BaseMatrix& X)
+{
+   REPORT  // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::RV);
+   if (nrows_value!=1)
+      { Tracer tr("RowVector(=)"); Throw(VectorException(*this)); }
+}
+
+void ColumnVector::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::CV);
+   if (ncols_value!=1)
+      { Tracer tr("ColumnVector(=)"); Throw(VectorException(*this)); }
+}
+
+void SymmetricMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Sm);
+}
+
+void UpperTriangularMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::UT);
+}
+
+void LowerTriangularMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::LT);
+}
+
+void DiagonalMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Dg);
+}
+
+void IdentityMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Id);
+}
+
+void GeneralMatrix::operator<<(const Real* r)
+{
+   REPORT
+   int i = storage; Real* s=store;
+   while(i--) *s++ = *r++;
+}
+
+
+void GeneralMatrix::operator<<(const int* r)
+{
+   REPORT
+   int i = storage; Real* s=store;
+   while(i--) *s++ = *r++;
+}
+
+
+void GenericMatrix::operator=(const GenericMatrix& bmx)
+{
+   if (&bmx != this) { REPORT if (gm) delete gm; gm = bmx.gm->Image();}
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator=(const BaseMatrix& bmx)
+{
+   if (gm)
+   {
+      int counter=bmx.search(gm);
+      if (counter==0) { REPORT delete gm; gm=0; }
+      else { REPORT gm->Release(counter); }
+   }
+   else { REPORT }
+   GeneralMatrix* gmx = ((BaseMatrix&)bmx).Evaluate();
+   if (gmx != gm) { REPORT if (gm) delete gm; gm = gmx->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+
+/*************************** += etc ***************************************/
+
+// will also need versions for SubMatrix
+
+
+
+// GeneralMatrix operators
+
+void GeneralMatrix::operator+=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator+=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   AddedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,Type());
+}
+
+void GeneralMatrix::operator-=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator-=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   SubtractedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,Type());
+}
+
+void GeneralMatrix::operator*=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator*=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   MultipliedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,Type());
+}
+
+void GeneralMatrix::operator|=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator|=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   ConcatenatedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,Type());
+}
+
+void GeneralMatrix::operator&=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator&=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   StackedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,Type());
+}
+
+void GeneralMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator+=(Real)");
+   // MatrixConversionCheck mcc;
+   ShiftedMatrix am(this,r);
+   Release(); Eq2(am,Type());
+}
+
+void GeneralMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator*=(Real)");
+   // MatrixConversionCheck mcc;
+   ScaledMatrix am(this,r);
+   Release(); Eq2(am,Type());
+}
+
+
+// Generic matrix operators
+
+void GenericMatrix::operator+=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator+=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   AddedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator-=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator-=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   SubtractedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator*=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator*=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   MultipliedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator|=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator|=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   ConcatenatedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator&=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator&=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   StackedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator+= (Real)");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   ShiftedMatrix am(gm,r);
+   gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator*= (Real)");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   ScaledMatrix am(gm,r);
+   gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+
+/************************* element access *********************************/
+
+Real& Matrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_value+n];
+}
+
+Real Matrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_value+n];
+}
+
+Real& SymmetricMatrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || n<0 || m >= nrows_value || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   if (m>=n) return store[tristore(m)+n];
+   else return store[tristore(n)+m];
+}
+
+Real SymmetricMatrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || n<0 || m >= nrows_value || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   if (m>=n) return store[tristore(m)+n];
+   else return store[tristore(n)+m];
+}
+
+Real& UpperTriangularMatrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || n<m || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_value+n-tristore(m)];
+}
+
+Real UpperTriangularMatrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || n<m || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_value+n-tristore(m)];
+}
+
+Real& LowerTriangularMatrix::element(int m, int n)
+{
+   REPORT
+   if (n<0 || m<n || m>=nrows_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[tristore(m)+n];
+}
+
+Real LowerTriangularMatrix::element(int m, int n) const
+{
+   REPORT
+   if (n<0 || m<n || m>=nrows_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[tristore(m)+n];
+}
+
+Real& DiagonalMatrix::element(int m, int n)
+{
+   REPORT
+   if (n<0 || m!=n || m>=nrows_value || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[n];
+}
+
+Real DiagonalMatrix::element(int m, int n) const
+{
+   REPORT
+   if (n<0 || m!=n || m>=nrows_value || n>=ncols_value)
+      Throw(IndexException(m,n,*this,true));
+   return store[n];
+}
+
+Real& DiagonalMatrix::element(int m)
+{
+   REPORT
+   if (m<0 || m>=nrows_value) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real DiagonalMatrix::element(int m) const
+{
+   REPORT
+   if (m<0 || m>=nrows_value) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real& ColumnVector::element(int m)
+{
+   REPORT
+   if (m<0 || m>= nrows_value) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real ColumnVector::element(int m) const
+{
+   REPORT
+   if (m<0 || m>= nrows_value) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real& RowVector::element(int n)
+{
+   REPORT
+   if (n<0 || n>= ncols_value)  Throw(IndexException(n,*this,true));
+   return store[n];
+}
+
+Real RowVector::element(int n) const
+{
+   REPORT
+   if (n<0 || n>= ncols_value)  Throw(IndexException(n,*this,true));
+   return store[n];
+}
+
+Real& BandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = upper+lower+1; int i = lower+n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real BandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = upper+lower+1; int i = lower+n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& UpperBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = upper+1; int i = n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real UpperBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = upper+1; int i = n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& LowerBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = lower+1; int i = lower+n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real LowerBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = lower+1; int i = lower+n-m;
+   if (m<0 || m>= nrows_value || n<0 || n>= ncols_value || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& SymmetricBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = lower+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower+n-m;
+      if ( m>=nrows_value || n<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*m+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower+m-n;
+      if ( n>=nrows_value || m<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*n+i];
+   }
+}
+
+Real SymmetricBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = lower+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower+n-m;
+      if ( m>=nrows_value || n<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*m+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower+m-n;
+      if ( n>=nrows_value || m<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*n+i];
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat7.cpp
===================================================================
RCS file: Shared/newmat/newmat7.cpp
diff -N Shared/newmat/newmat7.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat7.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,1029 @@
+//$$ newmat7.cpp     Invert, solve, binary operations
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+//***************************** solve routines ******************************/
+
+GeneralMatrix* GeneralMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new CroutMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+GeneralMatrix* Matrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new CroutMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el;
+   while (i--) *el++ = 0.0;
+   el += mcin.storage; i = nrows_value - mcin.skip - mcin.storage;
+   while (i--) *el++ = 0.0;
+   lubksb(el1, mcout.skip);
+}
+
+
+// Do we need check for entirely zero output?
+
+void UpperTriangularMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nr = mcin.skip+mcin.storage;
+   elx = mcin.data+mcin.storage; Real* el = elx;
+   int j = mcout.skip+mcout.storage-nr;
+   int nc = ncols_value-nr; i = nr-mcout.skip;
+   while (j-- > 0) *elx++ = 0.0;
+   Real* Ael = store + (nr*(2*ncols_value-nr+1))/2; j = 0;
+   while (i-- > 0)
+   {
+      elx = el; Real sum = 0.0; int jx = j++; Ael -= nc;
+      while (jx--) sum += *(--Ael) * *(--elx);
+      elx--; *elx = (*elx - sum) / *(--Ael);
+   }
+}
+
+void LowerTriangularMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
+   int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
+   while (j-- > 0) *elx++ = 0.0;
+   Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0;
+   while (i-- > 0)
+   {
+      elx = el; Real sum = 0.0; int jx = j++; Ael += nc;
+      while (jx--) sum += *Ael++ * *elx++;
+      *elx = (*elx - sum) / *Ael++;
+   }
+}
+
+//******************* carry out binary operations *************************/
+
+static GeneralMatrix*
+   GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType);
+
+GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+   gm2 = gm2->Evaluate(gm2->Type().MultRHS());     // no symmetric on RHS
+   gm1=((BaseMatrix*&)bm1)->Evaluate();
+   return GeneralMult(gm1, gm2, this, mt);
+}
+
+GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm1=((BaseMatrix*&)bm1)->Evaluate();
+   gm2=((BaseMatrix*&)bm2)->Evaluate();
+   return GeneralSolv(gm1,gm2,this,mt);
+}
+
+GeneralMatrix* KPMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm1=((BaseMatrix*&)bm1)->Evaluate();
+   gm2=((BaseMatrix*&)bm2)->Evaluate();
+   return GeneralKP(gm1,gm2,this,mt);
+}
+
+// routines for adding or subtracting matrices of identical storage structure
+
+static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
+       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++;
+}
+
+static void AddTo(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ += *s2++;
+}
+
+void GeneralMatrix::PlusEqual(const GeneralMatrix& gm)
+{
+   REPORT
+   if (nrows_value != gm.nrows_value || ncols_value != gm.ncols_value)
+      Throw(IncompatibleDimensionsException(*this, gm));
+   AddTo(this, &gm);
+}
+
+static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
+       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++;
+}
+
+static void SubtractFrom(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ -= *s2++;
+}
+
+void GeneralMatrix::MinusEqual(const GeneralMatrix& gm)
+{
+   REPORT
+   if (nrows_value != gm.nrows_value || ncols_value != gm.ncols_value)
+      Throw(IncompatibleDimensionsException(*this, gm));
+   SubtractFrom(this, &gm);
+}
+
+static void ReverseSubtract(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
+      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
+   }
+   i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; }
+}
+
+static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
+       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++;
+}
+
+static void SP(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ *= *s2++;
+}
+
+// routines for adding or subtracting matrices of different storage structure
+
+static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+// Add into first argument
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); }
+}
+
+static void SubtractDS
+   (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); }
+}
+
+static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); }
+}
+
+static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+// SP into first argument
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); }
+}
+
+static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralMult1");
+   int nr=gm1->Nrows(); int nc=gm2->Ncols();
+   if (gm1->Ncols() !=gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
+
+   MatrixCol mcx(gmx, StoreOnExit+DirectPart);
+   MatrixCol mc2(gm2, LoadOnEntry);
+   while (nc--)
+   {
+      MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip());
+      Real* el = mcx.Data();                         // pointer to an element
+      int n = mcx.Storage();
+      while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); }
+      mc2.Next(); mcx.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   // version that accesses by row only - not good for thin matrices
+   // or column vectors in right hand term.
+   REPORT
+   Tracer tr("GeneralMult2");
+   int nr=gm1->Nrows(); int nc=gm2->Ncols();
+   if (gm1->Ncols() !=gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
+
+   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr1(gm1, LoadOnEntry);
+   while (nr--)
+   {
+      MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip());
+      Real* el = mr1.Data();                         // pointer to an element
+      int n = mr1.Storage();
+      mrx.Zero();
+      while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); }
+      mr1.Next(); mrx.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   // matrix multiplication for type Matrix only
+   REPORT
+   Tracer tr("MatrixMult");
+
+   int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols();
+   if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2));
+
+   Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm);
+
+   Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store();
+
+   if (ncr)
+   {
+      while (nr--)
+      {
+         Real* s2x = s2; int j = ncr;
+         Real* sx = s; Real f = *s1++; int k = nc;
+         while (k--) *sx++ = f * *s2x++;
+         while (--j)
+            { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; }
+         s = sx;
+      }
+   }
+   else *gm = 0.0;
+
+   gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm;
+}
+
+static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   if ( Rectangular(gm1->Type(), gm2->Type(), mtx))
+   {
+      REPORT
+      return mmMult(gm1, gm2);
+   }
+   else
+   {
+      REPORT
+      Compare(gm1->Type() * gm2->Type(),mtx);
+      int nr = gm2->Nrows(); int nc = gm2->Ncols();
+      if (nc <= 5 && nr > nc) { REPORT return GeneralMult1(gm1, gm2, mm, mtx); }
+      else { REPORT return GeneralMult2(gm1, gm2, mm, mtx); }
+   }
+}
+
+static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   KPMatrix* kp, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralKP");
+   int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols();
+   int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols();
+   Compare((gm1->Type()).KP(gm2->Type()),mtx);
+   GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp);
+   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr1(gm1, LoadOnEntry);
+   for (int i = 1; i <= nr1; ++i)
+   {
+      MatrixRow mr2(gm2, LoadOnEntry);
+      for (int j = 1; j <= nr2; ++j)
+         { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); }
+      mr1.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   BaseMatrix* sm, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralSolv");
+   Compare(gm1->Type().i() * gm2->Type(),mtx);
+   int nr = gm1->Nrows();
+   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
+   int nc = gm2->Ncols();
+   if (gm1->Ncols() != gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
+   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
+   MONITOR_REAL_NEW("Make   (GenSolv)",nr,r)
+   GeneralMatrix* gms = gm1->MakeSolver();
+   Try
+   {
+
+      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
+         // this must be inside Try so mcx is destroyed before gmx
+      MatrixColX mc2(gm2, r, LoadOnEntry);
+      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
+   }
+   CatchAll
+   {
+      if (gms) gms->tDelete();
+      delete gmx;                   // <--------------------
+      gm2->tDelete();
+      MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+      delete [] r;
+      ReThrow;
+   }
+   gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
+   MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+   delete [] r;
+   return gmx;
+}
+
+// version for inverses - gm2 is identity
+static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm,
+   MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralSolvI");
+   Compare(gm1->Type().i(),mtx);
+   int nr = gm1->Nrows();
+   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
+   int nc = nr;
+   // DiagonalMatrix I(nr); I = 1;
+   IdentityMatrix I(nr);
+   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
+   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
+   MONITOR_REAL_NEW("Make   (GenSolvI)",nr,r)
+   GeneralMatrix* gms = gm1->MakeSolver();
+   Try
+   {
+
+      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
+         // this must be inside Try so mcx is destroyed before gmx
+      MatrixColX mc2(&I, r, LoadOnEntry);
+      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
+   }
+   CatchAll
+   {
+      if (gms) gms->tDelete();
+      delete gmx;
+      MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+      delete [] r;
+      ReThrow;
+   }
+   gms->tDelete(); gmx->ReleaseAndDelete();
+   MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+   delete [] r;
+   return gmx;
+}
+
+GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
+{
+   // Matrix Inversion - use solve routines
+   Tracer tr("InvertedMatrix::Evaluate");
+   REPORT
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   return GeneralSolvI(gm,this,mtx);
+}
+
+//*************************** New versions ************************
+
+GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("AddedMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2;
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      REPORT
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse()) { REPORT AddTo(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT AddTo(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         // what if new throws an exception
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c1 = false; }
+         if (SAO & 2) { REPORT c2 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+         { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         AddDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("SubtractedMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2;
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse())
+         { REPORT SubtractFrom(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c1 = false; }
+         if (SAO & 2) { REPORT c2 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+      {
+         REPORT ReverseSubtractDS(gm2,gm1);
+         if (!c1) gm1->tDelete(); gmx = gm2;
+      }
+      else
+      {
+         REPORT
+         // what if New throws and exception
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         SubtractDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("SPMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type();
+   MatrixType mts = mt1.SP(mt2);
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c2 = false; }    // c1 and c2 swapped
+         if (SAO & 2) { REPORT c1 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+         { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
+      else
+      {
+         REPORT
+         // what if New throws and exception
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         SPDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+
+
+//*************************** norm functions ****************************/
+
+Real BaseMatrix::Norm1() const
+{
+   // maximum of sum of absolute values of a column
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nc = gm->Ncols(); Real value = 0.0;
+   MatrixCol mc(gm, LoadOnEntry);
+   while (nc--)
+      { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); }
+   gm->tDelete(); return value;
+}
+
+Real BaseMatrix::NormInfinity() const
+{
+   // maximum of sum of absolute values of a row
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->Nrows(); Real value = 0.0;
+   MatrixRow mr(gm, LoadOnEntry);
+   while (nr--)
+      { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); }
+   gm->tDelete(); return value;
+}
+
+//********************** Concatenation and stacking *************************/
+
+GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx)
+{
+   REPORT
+   Tracer tr("Concatenate");
+      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+      Compare(gm1->Type() | gm2->Type(),mtx);
+      int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
+      if (nr != gm2->Nrows())
+         Throw(IncompatibleDimensionsException(*gm1, *gm2));
+      GeneralMatrix* gmx = mtx.New(nr,nc,this);
+      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+      MatrixRow mr(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx)
+{
+   REPORT
+   Tracer tr("Stack");
+      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+      Compare(gm1->Type() & gm2->Type(),mtx);
+      int nc=gm1->Ncols();
+      int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
+      if (nc != gm2->Ncols())
+         Throw(IncompatibleDimensionsException(*gm1, *gm2));
+      GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
+      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+      MatrixRow mr(gmx, StoreOnExit+DirectPart);
+      while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
+      while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+// ************************* equality of matrices ******************** //
+
+static bool RealEqual(Real* s1, Real* s2, int n)
+{
+   int i = n >> 2;
+   while (i--)
+   {
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+   }
+   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
+   return true;
+}
+
+static bool intEqual(int* s1, int* s2, int n)
+{
+   int i = n >> 2;
+   while (i--)
+   {
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+   }
+   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
+   return true;
+}
+
+
+bool operator==(const BaseMatrix& A, const BaseMatrix& B)
+{
+   Tracer tr("BaseMatrix ==");
+   REPORT
+   GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate();
+   GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate();
+
+   if (gmA == gmB)                            // same matrix
+      { REPORT gmA->tDelete(); return true; }
+
+   if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
+                                              // different dimensions
+      { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
+
+   // check for CroutMatrix or BandLUMatrix
+   MatrixType AType = gmA->Type(); MatrixType BType = gmB->Type();
+   if (AType.CannotConvert() || BType.CannotConvert() )
+   {
+      REPORT
+      bool bx = gmA->IsEqual(*gmB);
+      gmA->tDelete(); gmB->tDelete();
+      return bx;
+   }
+
+   // is matrix storage the same
+   // will need to modify if further matrix structures are introduced
+   if (AType == BType && gmA->BandWidth() == gmB->BandWidth())
+   {                                          // compare store
+      REPORT
+      bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
+      gmA->tDelete(); gmB->tDelete();
+      return bx;
+   }
+
+   // matrix storage different - just subtract
+   REPORT  return IsZero(*gmA-*gmB);
+}
+
+bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   Tracer tr("GeneralMatrix ==");
+   // May or may not call tDeletes
+   REPORT
+
+   if (&A == &B)                              // same matrix
+      { REPORT return true; }
+
+   if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
+      { REPORT return false; }                // different dimensions
+
+   // check for CroutMatrix or BandLUMatrix
+   MatrixType AType = A.Type(); MatrixType BType = B.Type();
+   if (AType.CannotConvert() || BType.CannotConvert() )
+      { REPORT  return A.IsEqual(B); }
+
+   // is matrix storage the same
+   // will need to modify if further matrix structures are introduced
+   if (AType == BType && A.BandWidth() == B.BandWidth())
+      { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
+
+   // matrix storage different - just subtract
+   REPORT  return IsZero(A-B);
+}
+
+bool GeneralMatrix::IsZero() const
+{
+   REPORT
+   Real* s=store; int i = storage >> 2;
+   while (i--)
+   {
+      if (*s++) return false; if (*s++) return false;
+      if (*s++) return false; if (*s++) return false;
+   }
+   i = storage & 3; while (i--) if (*s++) return false;
+   return true;
+}
+
+bool IsZero(const BaseMatrix& A)
+{
+   Tracer tr("BaseMatrix::IsZero");
+   REPORT
+   GeneralMatrix* gm1 = 0; bool bx;
+   Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->IsZero(); }
+   CatchAll { if (gm1) gm1->tDelete(); ReThrow; }
+   gm1->tDelete();
+   return bx;
+}
+
+// IsEqual functions - insist matrices are of same type
+// as well as equal values to be equal
+
+bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("GeneralMatrix IsEqual");
+   if (A.Type() != Type())                       // not same types
+      { REPORT return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if (A.nrows_value != nrows_value || A.ncols_value != ncols_value)
+                                                 // different dimensions
+   { REPORT return false; }
+   // is matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.store,store,storage);
+}
+
+bool CroutMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("CroutMatrix IsEqual");
+   if (A.Type() != Type())                       // not same types
+      { REPORT return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if (A.nrows_value != nrows_value || A.ncols_value != ncols_value)
+                                                 // different dimensions
+   { REPORT return false; }
+   // is matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.store,store,storage)
+      && intEqual(((CroutMatrix&)A).indx, indx, nrows_value);
+}
+
+
+bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("BandLUMatrix IsEqual");
+   if (A.Type() != Type())                       // not same types
+      { REPORT  return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if ( A.Nrows() != nrows_value || A.Ncols() != ncols_value
+      || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
+                                                 // different dimensions
+   { REPORT  return false; }
+
+   // matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.Store(),store,storage)
+      && RealEqual(((BandLUMatrix&)A).store2,store2,storage2)
+      && intEqual(((BandLUMatrix&)A).indx, indx, nrows_value);
+}
+
+
+// ************************* cross products ******************** //
+
+inline void CrossProductBody(Real* a, Real* b, Real* c)
+{
+   c[0] = a[1] * b[2] - a[2] * b[1];
+   c[1] = a[2] * b[0] - a[0] * b[2];
+   c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+Matrix CrossProduct(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int ac = A.Ncols(); int ar = A.Nrows();
+   int bc = B.Ncols(); int br = B.Nrows();
+   Real* a = A.Store(); Real* b = B.Store();
+   if (ac == 3)
+   {
+      if (bc != 3 || ar != 1 || br != 1)
+         { Tracer et("CrossProduct"); IncompatibleDimensionsException(A, B); }
+      REPORT
+      RowVector C(3);  Real* c = C.Store(); CrossProductBody(a, b, c);
+      return (Matrix&)C;
+   }
+   else
+   {
+      if (ac != 1 || bc != 1 || ar != 3 || br != 3)
+         { Tracer et("CrossProduct"); IncompatibleDimensionsException(A, B); }
+      REPORT
+      ColumnVector C(3);  Real* c = C.Store(); CrossProductBody(a, b, c);
+      return (Matrix&)C;
+   }
+}
+
+ReturnMatrix CrossProductRows(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.Nrows();
+   if (A.Ncols() != 3 || B.Ncols() != 3 || n != B.Nrows())
+      { Tracer et("CrossProductRows"); IncompatibleDimensionsException(A, B); }
+   Matrix C(n, 3);
+   Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
+   if (n--)
+   {
+      for (;;)
+      {
+         CrossProductBody(a, b, c);
+         if (!(n--)) break;
+         a += 3; b += 3; c += 3;
+      }
+   }
+
+   return C.ForReturn();
+}
+
+ReturnMatrix CrossProductColumns(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.Ncols();
+   if (A.Nrows() != 3 || B.Nrows() != 3 || n != B.Ncols())
+      { Tracer et("CrossProductColumns"); IncompatibleDimensionsException(A, B); }
+   Matrix C(3, n);
+   Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
+   Real* an = a+n; Real* an2 = an+n;
+   Real* bn = b+n; Real* bn2 = bn+n;
+   Real* cn = c+n; Real* cn2 = cn+n;
+
+   int i = n; 
+   while (i--)
+   {
+      *c++   = *an    * *bn2   - *an2   * *bn;
+      *cn++  = *an2++ * *b     - *a     * *bn2++;
+      *cn2++ = *a++   * *bn++  - *an++  * *b++;
+   }
+
+   return C.ForReturn();
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/newmat8.cpp
===================================================================
RCS file: Shared/newmat/newmat8.cpp
diff -N Shared/newmat/newmat8.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat8.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,736 @@
+//$$ newmat8.cpp         Advanced LU transform, scalar functions
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************** LU transformation ****************************/
+
+void CroutMatrix::ludcmp()
+// LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer
+// product" version).
+// This replaces the code derived from Numerical Recipes in C in previous
+// versions of newmat and being row oriented runs much faster with large
+// matrices.
+{
+   REPORT
+   Tracer trace( "Crout(ludcmp)" ); sing = false;
+   Real* akk = store;                    // runs down diagonal
+
+   Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k;
+
+   for (k = 1; k < nrows_value; k++)
+   {
+      ai += nrows_value; const Real trybig = fabs(*ai);
+      if (big < trybig) { big = trybig; mu = k; }
+   }
+
+
+   if (nrows_value) for (k = 0;;)
+   {
+      /*
+      int mu1;
+      {
+         Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i;
+
+         for (i = k+1; i < nrows_value; i++)
+         {
+            ai += nrows_value; const Real trybig = fabs(*ai);
+            if (big < trybig) { big = trybig; mu1 = i; }
+         }
+      }
+      if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl;
+      */
+
+      indx[k] = mu;
+
+      if (mu != k)                       //row swap
+      {
+         Real* a1 = store + nrows_value * k;
+         Real* a2 = store + nrows_value * mu; d = !d;
+         int j = nrows_value;
+         while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; }
+      }
+
+      Real diag = *akk; big = 0; mu = k + 1;
+      if (diag != 0)
+      {
+         ai = akk; int i = nrows_value - k - 1;
+         while (i--)
+         {
+            ai += nrows_value; Real* al = ai;
+            Real mult = *al / diag; *al = mult;
+            int l = nrows_value - k - 1; Real* aj = akk;
+            // work out the next pivot as part of this loop
+            // this saves a column operation
+            if (l-- != 0)
+            {
+               *(++al) -= (mult * *(++aj));
+               const Real trybig = fabs(*al);
+               if (big < trybig) { big = trybig; mu = nrows_value - i - 1; }
+               while (l--) *(++al) -= (mult * *(++aj));
+            }
+         }
+      }
+      else sing = true;
+      if (++k == nrows_value) break;          // so next line won't overflow
+      akk += nrows_value + 1;
+   }
+}
+
+void CroutMatrix::lubksb(Real* B, int mini)
+{
+   REPORT
+   // this has been adapted from Numerical Recipes in C. The code has been
+   // substantially streamlined, so I do not think much of the original
+   // copyright remains. However there is not much opportunity for
+   // variation in the code, so it is still similar to the NR code.
+   // I follow the NR code in skipping over initial zeros in the B vector.
+
+   Tracer trace("Crout(lubksb)");
+   if (sing) Throw(SingularException(*this));
+   int i, j, ii = nrows_value;       // ii initialised : B might be all zeros
+
+
+   // scan for first non-zero in B
+   for (i = 0; i < nrows_value; i++)
+   {
+      int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp;
+      if (temp != 0.0) { ii = i; break; }
+   }
+
+   Real* bi; Real* ai;
+   i = ii + 1;
+
+   if (i < nrows_value)
+   {
+      bi = B + ii; ai = store + ii + i * nrows_value;
+      for (;;)
+      {
+         int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i];
+         Real* aij = ai; Real* bj = bi; j = i - ii;
+         while (j--) sum -= *aij++ * *bj++;
+         B[i] = sum;
+         if (++i == nrows_value) break;
+         ai += nrows_value;
+      }
+   }
+
+   ai = store + nrows_value * nrows_value;
+
+   for (i = nrows_value - 1; i >= mini; i--)
+   {
+      Real* bj = B+i; ai -= nrows_value; Real* ajx = ai+i;
+      Real sum = *bj; Real diag = *ajx;
+      j = nrows_value - i; while(--j) sum -= *(++ajx) * *(++bj);
+      B[i] = sum / diag;
+   }
+}
+
+/****************************** scalar functions ****************************/
+
+inline Real square(Real x) { return x*x; }
+
+Real GeneralMatrix::SumSquare() const
+{
+   REPORT
+   Real sum = 0.0; int i = storage; Real* s = store;
+   while (i--) sum += square(*s++);
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real GeneralMatrix::SumAbsoluteValue() const
+{
+   REPORT
+   Real sum = 0.0; int i = storage; Real* s = store;
+   while (i--) sum += fabs(*s++);
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real GeneralMatrix::Sum() const
+{
+   REPORT
+   Real sum = 0.0; int i = storage; Real* s = store;
+   while (i--) sum += *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+// maxima and minima
+
+// There are three sets of routines
+// MaximumAbsoluteValue, MinimumAbsoluteValue, Maximum, Minimum
+// ... these find just the maxima and minima
+// MaximumAbsoluteValue1, MinimumAbsoluteValue1, Maximum1, Minimum1
+// ... these find the maxima and minima and their locations in a
+//     one dimensional object
+// MaximumAbsoluteValue2, MinimumAbsoluteValue2, Maximum2, Minimum2
+// ... these find the maxima and minima and their locations in a
+//     two dimensional object
+
+// If the matrix has no values throw an exception
+
+// If we do not want the location find the maximum or minimum on the
+// array stored by GeneralMatrix
+// This won't work for BandMatrices. We call ClearCorner for
+// MaximumAbsoluteValue but for the others use the AbsoluteMinimumValue2
+// version and discard the location.
+
+// For one dimensional objects, when we want the location of the
+// maximum or minimum, work with the array stored by GeneralMatrix
+
+// For two dimensional objects where we want the location of the maximum or
+// minimum proceed as follows:
+
+// For rectangular matrices use the array stored by GeneralMatrix and
+// deduce the location from the location in the GeneralMatrix
+
+// For other two dimensional matrices use the Matrix Row routine to find the
+// maximum or minimum for each row.
+
+static void NullMatrixError(const GeneralMatrix* gm)
+{
+   ((GeneralMatrix&)*gm).tDelete();
+   Throw(ProgramException("Maximum or minimum of null matrix"));
+}
+
+Real GeneralMatrix::MaximumAbsoluteValue() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int l = storage; Real* s = store;
+   while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::MaximumAbsoluteValue1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int l = storage; Real* s = store; int li = storage;
+   while (l--)
+      { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; }  }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::MinimumAbsoluteValue() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = fabs(*s++);
+   while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::MinimumAbsoluteValue1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l;
+   while (l--)
+      { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; }  }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::Maximum() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real maxval = *s++;
+   while (l--) { Real a = *s++; if (maxval < a) maxval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::Maximum1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l;
+   while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::Minimum() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = *s++;
+   while (l--) { Real a = *s++; if (minval > a) minval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::Minimum1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = *s++; int li = l;
+   while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::MaximumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; maxval = mr.MaximumAbsoluteValue1(maxval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::MinimumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0)  NullMatrixError(this);
+   Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; minval = mr.MinimumAbsoluteValue1(minval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::Maximum2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; maxval = mr.Maximum1(maxval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::Minimum2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; minval = mr.Minimum1(minval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real Matrix::MaximumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::MaximumAbsoluteValue1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::MinimumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::MinimumAbsoluteValue1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::Maximum2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::Maximum1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::Minimum2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::Minimum1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real SymmetricMatrix::SumSquare() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_value;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += square(*s++);
+      sum1 += square(*s++);
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricMatrix::SumAbsoluteValue() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_value;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += fabs(*s++);
+      sum1 += fabs(*s++);
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real IdentityMatrix::SumAbsoluteValue() const
+   { REPORT  return fabs(Trace()); }    // no need to do tDelete?
+
+Real SymmetricMatrix::Sum() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_value;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += *s++;
+      sum1 += *s++;
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real IdentityMatrix::SumSquare() const
+{
+   Real sum = *store * *store * nrows_value;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+
+Real BaseMatrix::SumSquare() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->SumSquare(); return s;
+}
+
+Real BaseMatrix::NormFrobenius() const
+   { REPORT  return sqrt(SumSquare()); }
+
+Real BaseMatrix::SumAbsoluteValue() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->SumAbsoluteValue(); return s;
+}
+
+Real BaseMatrix::Sum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Sum(); return s;
+}
+
+Real BaseMatrix::MaximumAbsoluteValue() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MaximumAbsoluteValue(); return s;
+}
+
+Real BaseMatrix::MaximumAbsoluteValue1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MaximumAbsoluteValue1(i); return s;
+}
+
+Real BaseMatrix::MaximumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MaximumAbsoluteValue2(i, j); return s;
+}
+
+Real BaseMatrix::MinimumAbsoluteValue() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MinimumAbsoluteValue(); return s;
+}
+
+Real BaseMatrix::MinimumAbsoluteValue1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MinimumAbsoluteValue1(i); return s;
+}
+
+Real BaseMatrix::MinimumAbsoluteValue2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->MinimumAbsoluteValue2(i, j); return s;
+}
+
+Real BaseMatrix::Maximum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Maximum(); return s;
+}
+
+Real BaseMatrix::Maximum1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Maximum1(i); return s;
+}
+
+Real BaseMatrix::Maximum2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Maximum2(i, j); return s;
+}
+
+Real BaseMatrix::Minimum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Minimum(); return s;
+}
+
+Real BaseMatrix::Minimum1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Minimum1(i); return s;
+}
+
+Real BaseMatrix::Minimum2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->Minimum2(i, j); return s;
+}
+
+Real DotProduct(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.storage;
+   if (n != B.storage) Throw(IncompatibleDimensionsException(A,B));
+   Real sum = 0.0; Real* a = A.store; Real* b = B.store;
+   while (n--) sum += *a++ * *b++;
+   return sum;
+}
+
+Real Matrix::Trace() const
+{
+   REPORT
+   Tracer trace("Trace");
+   int i = nrows_value; int d = i+1;
+   if (i != ncols_value) Throw(NotSquareException(*this));
+   Real sum = 0.0; Real* s = store;
+//   while (i--) { sum += *s; s += d; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real DiagonalMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; Real sum = 0.0; Real* s = store;
+   while (i--) sum += *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real SymmetricMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; Real sum = 0.0; Real* s = store; int j = 2;
+   // while (i--) { sum += *s; s += j++; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real LowerTriangularMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; Real sum = 0.0; Real* s = store; int j = 2;
+   // while (i--) { sum += *s; s += j++; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real UpperTriangularMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; Real sum = 0.0; Real* s = store;
+   while (i) { sum += *s; s += i--; }             // won t cause a problem
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real BandMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; int w = lower+upper+1;
+   Real sum = 0.0; Real* s = store+lower;
+   // while (i--) { sum += *s; s += w; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real SymmetricBandMatrix::Trace() const
+{
+   REPORT
+   int i = nrows_value; int w = lower+1;
+   Real sum = 0.0; Real* s = store+lower;
+   // while (i--) { sum += *s; s += w; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real IdentityMatrix::Trace() const
+{
+   Real sum = *store * nrows_value;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+
+Real BaseMatrix::Trace() const
+{
+   REPORT
+   MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK();
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag);
+   Real sum = gm->Trace(); return sum;
+}
+
+void LogAndSign::operator*=(Real x)
+{
+   if (x > 0.0) { log_value += log(x); }
+   else if (x < 0.0) { log_value += log(-x); sign = -sign; }
+   else sign = 0;
+}
+
+void LogAndSign::PowEq(int k)
+{
+   if (sign)
+   {
+      log_value *= k;
+      if ( (k & 1) == 0 ) sign = 1;
+   }
+}
+
+Real LogAndSign::Value() const
+{
+   Tracer et("LogAndSign::Value");
+   if (log_value >= FloatingPointPrecision::LnMaximum())
+      Throw(OverflowException("Overflow in exponential"));
+   return sign * exp(log_value);
+}
+
+LogAndSign::LogAndSign(Real f)
+{
+   if (f == 0.0) { log_value = 0.0; sign = 0; return; }
+   else if (f < 0.0) { sign = -1; f = -f; }
+   else sign = 1;
+   log_value = log(f);
+}
+
+LogAndSign DiagonalMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum; Real* s = store;
+   while (i--) sum *= *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign LowerTriangularMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum; Real* s = store; int j = 2;
+   // while (i--) { sum *= *s; s += j++; }
+   if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign UpperTriangularMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum; Real* s = store;
+   while (i) { sum *= *s; s += i--; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign IdentityMatrix::LogDeterminant() const
+{
+   REPORT
+   int i = nrows_value; LogAndSign sum;
+   if (i > 0) { sum = *store; sum.PowEq(i); }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign BaseMatrix::LogDeterminant() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   LogAndSign sum = gm->LogDeterminant(); return sum;
+}
+
+LogAndSign GeneralMatrix::LogDeterminant() const
+{
+   REPORT
+   Tracer tr("LogDeterminant");
+   if (nrows_value != ncols_value) Throw(NotSquareException(*this));
+   CroutMatrix C(*this); return C.LogDeterminant();
+}
+
+LogAndSign CroutMatrix::LogDeterminant() const
+{
+   REPORT
+   if (sing) return 0.0;
+   int i = nrows_value; int dd = i+1; LogAndSign sum; Real* s = store;
+   if (i) for(;;)
+   {
+      sum *= *s;
+      if (!(--i)) break;
+      s += dd;
+   }
+   if (!d) sum.ChangeSign(); return sum;
+
+}
+
+Real BaseMatrix::Determinant() const
+{
+   REPORT
+   Tracer tr("Determinant");
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   LogAndSign ld = gm->LogDeterminant();
+   return ld.Value();
+}
+
+
+
+
+
+LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm)
+: gm( ( ((BaseMatrix&)bm).Evaluate() )->MakeSolver() )
+{
+   if (gm==&bm) { REPORT  gm = gm->Image(); }
+   // want a copy if  *gm is actually bm
+   else { REPORT  gm->Protect(); }
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmat9.cpp
===================================================================
RCS file: Shared/newmat/newmat9.cpp
diff -N Shared/newmat/newmat9.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmat9.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,76 @@
+//$$ newmat9.cpp         Input and output
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+
+#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatio.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,9); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+// for G++ 3.01
+#ifndef ios_format_flags
+#define ios_format_flags long
+#endif
+
+ostream& operator<<(ostream& s, const BaseMatrix& X)
+{
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); operator<<(s, *gm);
+   gm->tDelete(); return s;
+}
+
+
+ostream& operator<<(ostream& s, const GeneralMatrix& X)
+{
+   MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
+   int w = s.width();  int nr = X.Nrows();  ios_format_flags f = s.flags();
+   s.setf(ios::fixed, ios::floatfield);
+   for (int i=1; i<=nr; i++)
+   {
+      int skip = mr.skip;  int storage = mr.storage;
+      Real* store = mr.data;  skip *= w+1;
+      while (skip--) s << " ";
+      while (storage--) { s.width(w); s << *store++ << " "; }
+//      while (storage--) s << setw(w) << *store++ << " ";
+      mr.Next();  s << "\n";
+   }
+   s << flush;  s.flags(f); return s;
+}
+
+// include this stuff if you are using an old version of G++
+// with an incomplete io library
+
+/*
+
+ostream& operator<<(ostream& os, Omanip_precision i)
+   { os.precision(i.x); return os; }
+
+Omanip_precision setprecision(int i) { return Omanip_precision(i); }
+
+ostream& operator<<(ostream& os, Omanip_width i)
+   { os.width(i.x); return os; }
+
+Omanip_width setw(int i) { return Omanip_width(i); }
+
+*/
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/newmatap.h
===================================================================
RCS file: Shared/newmat/newmatap.h
diff -N Shared/newmat/newmatap.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatap.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,201 @@
+//$$ newmatap.h           definition file for matrix package applications
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+#ifndef NEWMATAP_LIB
+#define NEWMATAP_LIB 0
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+// ************************** applications *****************************/
+
+
+void QRZT(Matrix&, LowerTriangularMatrix&);
+
+void QRZT(const Matrix&, Matrix&, Matrix&);
+
+void QRZ(Matrix&, UpperTriangularMatrix&);
+
+void QRZ(const Matrix&, Matrix&, Matrix&);
+
+inline void HHDecompose(Matrix& X, LowerTriangularMatrix& L)
+{ QRZT(X,L); }
+
+inline void HHDecompose(const Matrix& X, Matrix& Y, Matrix& M)
+{ QRZT(X, Y, M); }
+
+void UpdateQRZT(Matrix& X, LowerTriangularMatrix& L);
+
+void UpdateQRZ(Matrix& X, UpperTriangularMatrix& U);
+
+
+ReturnMatrix Cholesky(const SymmetricMatrix&);
+
+ReturnMatrix Cholesky(const SymmetricBandMatrix&);
+
+
+// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol
+// and x is a RowVector
+void UpdateCholesky(UpperTriangularMatrix &chol, RowVector r1Modification);
+
+// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol
+// and x is a RowVector
+void DowndateCholesky(UpperTriangularMatrix &chol, RowVector x);
+
+// a RIGHT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,l,k,k+1,...l-1,l+1,...p
+void RightCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l);
+
+// a LEFT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,k+1,...l,k,l+1,...,p to
+void LeftCircularUpdateCholesky(UpperTriangularMatrix &chol, int k, int l); 
+
+
+void SVD(const Matrix&, DiagonalMatrix&, Matrix&, Matrix&,
+    bool=true, bool=true);
+
+void SVD(const Matrix&, DiagonalMatrix&);
+
+inline void SVD(const Matrix& A, DiagonalMatrix& D, Matrix& U,
+   bool withU = true) { SVD(A, D, U, U, withU, false); }
+
+void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending = false);
+
+void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending = false);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, Matrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&,
+   Matrix&, bool=true);
+
+void EigenValues(const SymmetricMatrix&, DiagonalMatrix&);
+
+void EigenValues(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&);
+
+void EigenValues(const SymmetricMatrix&, DiagonalMatrix&, Matrix&);
+
+class SymmetricEigenAnalysis
+// not implemented yet
+{
+public:
+   SymmetricEigenAnalysis(const SymmetricMatrix&);
+private:
+   DiagonalMatrix diag;
+   DiagonalMatrix offdiag;
+   SymmetricMatrix backtransform;
+   FREE_CHECK(SymmetricEigenAnalysis)
+};
+
+void SortAscending(GeneralMatrix&);
+
+void SortDescending(GeneralMatrix&);
+
+
+// class for deciding which fft to use and containing new fft function
+class FFT_Controller
+{
+public:
+   static bool OnlyOldFFT;
+   static bool ar_1d_ft (int PTS, Real* X, Real *Y);
+   static bool CanFactor(int PTS);
+};
+
+void FFT(const ColumnVector&, const ColumnVector&,
+   ColumnVector&, ColumnVector&);
+
+void FFTI(const ColumnVector&, const ColumnVector&,
+   ColumnVector&, ColumnVector&);
+
+void RealFFT(const ColumnVector&, ColumnVector&, ColumnVector&);
+
+void RealFFTI(const ColumnVector&, const ColumnVector&, ColumnVector&);
+
+void DCT_II(const ColumnVector&, ColumnVector&);
+
+void DCT_II_inverse(const ColumnVector&, ColumnVector&);
+
+void DST_II(const ColumnVector&, ColumnVector&);
+
+void DST_II_inverse(const ColumnVector&, ColumnVector&);
+
+void DCT(const ColumnVector&, ColumnVector&);
+
+void DCT_inverse(const ColumnVector&, ColumnVector&);
+
+void DST(const ColumnVector&, ColumnVector&);
+
+void DST_inverse(const ColumnVector&, ColumnVector&);
+
+void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y);
+
+void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y);
+
+
+// This class is used by the new FFT program
+
+// Suppose an integer is expressed as a sequence of digits with each
+// digit having a different radix.
+// This class supposes we are counting with this multi-radix number
+// but also keeps track of the number with the digits (and radices)
+// reversed.
+// The integer starts at zero
+// operator++() increases it by 1
+// Counter gives the number of increments
+// Reverse() gives the value with the digits in reverse order
+// Swap is true if reverse is less than counter
+// Finish is true when we have done a complete cycle and are back at zero
+
+class MultiRadixCounter
+{
+   const SimpleIntArray& Radix;
+                              // radix of each digit
+                              // n-1 highest order, 0 lowest order
+   SimpleIntArray& Value;     // value of each digit
+   const int n;               // number of digits
+   int reverse;               // value when order of digits is reversed
+   int product;               // product of radices
+   int counter;               // counter
+   bool finish;               // true when we have gone over whole range
+public:
+   MultiRadixCounter(int nx, const SimpleIntArray& rx,
+      SimpleIntArray& vx);
+   void operator++();         // increment the multi-radix counter
+   bool Swap() const { return reverse < counter; }
+   bool Finish() const { return finish; }
+   int Reverse() const { return reverse; }
+   int Counter() const { return counter; }
+};
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
+
+// body file: cholesky.cpp
+// body file: evalue.cpp
+// body file: fft.cpp
+// body file: hholder.cpp
+// body file: jacobi.cpp
+// body file: newfft.cpp
+// body file: sort.cpp
+// body file: svd.cpp
+
+
+
+
+
Index: Shared/newmat/newmatex.cpp
===================================================================
RCS file: Shared/newmat/newmatex.cpp
diff -N Shared/newmat/newmatex.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatex.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,313 @@
+//$$ newmatex.cpp                    Exception handler
+
+// Copyright (C) 1992,3,4,7: R B Davies
+
+#define WANT_STREAM                  // include.h will get stream fns
+
+#include "include.h"                 // include standard files
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+unsigned long OverflowException::Select;
+unsigned long SingularException::Select;
+unsigned long NPDException::Select;
+unsigned long ConvergenceException::Select;
+unsigned long ProgramException::Select;
+unsigned long IndexException::Select;
+unsigned long VectorException::Select;
+unsigned long NotSquareException::Select;
+unsigned long SubMatrixDimensionException::Select;
+unsigned long IncompatibleDimensionsException::Select;
+unsigned long NotDefinedException::Select;
+unsigned long CannotBuildException::Select;
+unsigned long InternalException::Select;
+
+
+
+static void MatrixDetails(const GeneralMatrix& A)
+// write matrix details to Exception buffer
+{
+   MatrixBandWidth bw = A.BandWidth(); int ubw = bw.upper; int lbw = bw.lower;
+   BaseException::AddMessage("MatrixType = ");
+   BaseException::AddMessage(A.Type().Value());
+   BaseException::AddMessage("  # Rows = "); BaseException::AddInt(A.Nrows());
+   BaseException::AddMessage("; # Cols = "); BaseException::AddInt(A.Ncols());
+   if (lbw >=0)
+   {
+      BaseException::AddMessage("; lower BW = ");
+      BaseException::AddInt(lbw);
+   }
+   if (ubw >=0)
+   {
+      BaseException::AddMessage("; upper BW = ");
+      BaseException::AddInt(ubw);
+   }
+   BaseException::AddMessage("\n");
+}
+
+NPDException::NPDException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix not positive definite\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+SingularException::SingularException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is singular\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+ConvergenceException::ConvergenceException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: process fails to converge\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+ConvergenceException::ConvergenceException(const char* c) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+OverflowException::OverflowException(const char* c) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   MatrixDetails(A);
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, const GeneralMatrix& A,
+   const GeneralMatrix& B) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   MatrixDetails(A); MatrixDetails(B);
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, MatrixType a, MatrixType b)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\nMatrixTypes = ");
+   AddMessage(a.Value()); AddMessage("; ");
+   AddMessage(b.Value()); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+VectorException::VectorException() : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
+   Tracer::AddTrace();
+}
+
+VectorException::VectorException(const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+NotSquareException::NotSquareException(const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is not square\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+NotSquareException::NotSquareException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is not square\n\n");
+   Tracer::AddTrace();
+}
+
+SubMatrixDimensionException::SubMatrixDimensionException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible submatrix dimension\n\n");
+   Tracer::AddTrace();
+}
+
+IncompatibleDimensionsException::IncompatibleDimensionsException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible dimensions\n\n");
+   Tracer::AddTrace();
+}
+
+IncompatibleDimensionsException::IncompatibleDimensionsException
+   (const GeneralMatrix& A, const GeneralMatrix& B)
+      : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible dimensions\n\n");
+   MatrixDetails(A); MatrixDetails(B);
+   Tracer::AddTrace();
+}
+
+NotDefinedException::NotDefinedException(const char* op, const char* matrix)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(op);
+   AddMessage(" not defined for ");
+   AddMessage(matrix);
+   AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+CannotBuildException::CannotBuildException(const char* matrix)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot build matrix type ");
+   AddMessage(matrix); AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: index error: requested index = ");
+   AddInt(i); AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, int j, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: index error: requested indices = ");
+   AddInt(i); AddMessage(", "); AddInt(j);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+
+IndexException::IndexException(int i, const GeneralMatrix& A, bool)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: element error: requested index (wrt 0) = ");
+   AddInt(i);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, int j, const GeneralMatrix& A, bool)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage(
+      "detected by Newmat: element error: requested indices (wrt 0) = ");
+   AddInt(i); AddMessage(", "); AddInt(j);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+InternalException::InternalException(const char* c) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("internal error detected by Newmat: please inform author\n");
+   AddMessage(c); AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+
+
+
+/************************* ExeCounter functions *****************************/
+
+#ifdef DO_REPORT
+
+int ExeCounter::nreports;                      // will be set to zero
+
+ExeCounter::ExeCounter(int xl, int xf) : line(xl), fileid(xf), nexe(0) {}
+
+ExeCounter::~ExeCounter()
+{
+   nreports++;
+   cout << "REPORT  " << setw(6) << nreports << "  "
+      << setw(6) << fileid << "  " << setw(6) << line
+      << "  " << setw(6) << nexe << "\n";
+}
+
+#endif
+
+/**************************** error handler *******************************/
+
+void MatrixErrorNoSpace(const void* v) { if (!v) Throw(Bad_alloc()); }
+// throw exception if v is null
+
+
+
+
+/************************* miscellanous errors ***************************/
+
+
+void CroutMatrix::GetRow(MatrixRowCol&)
+   { Throw(NotDefinedException("GetRow","Crout")); }
+void CroutMatrix::GetCol(MatrixRowCol&)
+   { Throw(NotDefinedException("GetCol","Crout")); }
+void BandLUMatrix::GetRow(MatrixRowCol&)
+   { Throw(NotDefinedException("GetRow","BandLUMatrix")); }
+void BandLUMatrix::GetCol(MatrixRowCol&)
+   { Throw(NotDefinedException("GetCol","BandLUMatrix")); }
+void BaseMatrix::IEQND() const
+   { Throw(NotDefinedException("inequalities", "matrices")); }
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmatio.h
===================================================================
RCS file: Shared/newmat/newmatio.h
diff -N Shared/newmat/newmatio.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatio.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,61 @@
+//$$ newmatio.h           definition file for matrix package input/output
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#ifndef NEWMATIO_LIB
+#define NEWMATIO_LIB 0
+
+#ifndef WANT_STREAM
+#define WANT_STREAM
+#endif
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+/**************************** input/output *****************************/
+
+ostream& operator<<(ostream&, const BaseMatrix&);
+
+ostream& operator<<(ostream&, const GeneralMatrix&);
+
+
+/*  Use in some old versions of G++ without complete iomanipulators
+
+class Omanip_precision
+{
+   int x;
+public:
+   Omanip_precision(int i) : x(i) {}
+   friend ostream& operator<<(ostream& os, Omanip_precision i);
+};
+
+
+Omanip_precision setprecision(int i);
+
+class Omanip_width
+{
+   int x;
+public:
+   Omanip_width(int i) : x(i) {}
+   friend ostream& operator<<(ostream& os, Omanip_width i);
+};
+
+Omanip_width setw(int i);
+
+*/
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
+
+// body file: newmat9.cpp
+
Index: Shared/newmat/newmatnl.cpp
===================================================================
RCS file: Shared/newmat/newmatnl.cpp
diff -N Shared/newmat/newmatnl.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatnl.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,260 @@
+//$$ newmatnl.cpp         Non-linear optimisation
+
+// Copyright (C) 1993,4,5,6: R B Davies
+
+
+#define WANT_MATH
+#define WANT_STREAM
+
+#include "newmatap.h"
+#include "newmatnl.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+void FindMaximum2::Fit(ColumnVector& Theta, int n_it)
+{
+   Tracer tr("FindMaximum2::Fit");
+   enum State {Start, Restart, Continue, Interpolate, Extrapolate,
+      Fail, Convergence};
+   State TheState = Start;
+   Real z,w,x,x2,g,l1,l2,l3,d1,d2=0,d3;
+   ColumnVector Theta1, Theta2, Theta3;
+   int np = Theta.Nrows();
+   ColumnVector H1(np), H3, HP(np), K, K1(np);
+   bool oorg, conv;
+   int counter = 0;
+   Theta1 = Theta; HP = 0.0; g = 0.0;
+
+   // This is really a set of gotos and labels, but they do not work
+   // correctly in AT&T C++ and Sun 4.01 C++.
+
+   for(;;)
+   {
+      switch (TheState)
+      {
+      case Start:
+	 tr.ReName("FindMaximum2::Fit/Start");
+	 Value(Theta1, true, l1, oorg);
+	 if (oorg) Throw(ProgramException("invalid starting value\n"));
+
+      case Restart:
+	 tr.ReName("FindMaximum2::Fit/ReStart");
+	 conv = NextPoint(H1, d1);
+	 if (conv) { TheState = Convergence; break; }
+	 if (counter++ > n_it) { TheState = Fail; break; }
+
+	 z = 1.0 / sqrt(d1);
+	 H3 = H1 * z; K = (H3 - HP) * g; HP = H3;
+	 g = 0.0;                     // de-activate to use curved projection
+	 if (g==0.0) K1 = 0.0; else K1 = K * 0.2 + K1 * 0.6;
+	 // (K - K1) * alpha + K1 * (1 - alpha)
+	 //     = K * alpha + K1 * (1 - 2 * alpha)
+	 K = K1 * d1; g = z;
+
+      case Continue:
+	 tr.ReName("FindMaximum2::Fit/Continue");
+	 Theta2 = Theta1 + H1 + K;
+	 Value(Theta2, false, l2, oorg);
+	 if (counter++ > n_it) { TheState = Fail; break; }
+	 if (oorg)
+	 {
+	    H1 *= 0.5; K *= 0.25; d1 *= 0.5; g *= 2.0;
+	    TheState =  Continue; break;
+	 }
+	 d2 = LastDerivative(H1 + K * 2.0);
+
+      case Interpolate:
+	 tr.ReName("FindMaximum2::Fit/Interpolate");
+	 z = d1 + d2 - 3.0 * (l2 - l1);
+	 w = z * z - d1 * d2;
+	 if (w < 0.0) { TheState = Extrapolate; break; }
+	 w = z + sqrt(w);
+	 if (1.5 * w + d1 < 0.0)
+	    { TheState = Extrapolate; break; }
+	 if (d2 > 0.0 && l2 > l1 && w > 0.0)
+	    { TheState = Extrapolate; break; }
+	 x = d1 / (w + d1); x2 = x * x; g /= x;
+	 Theta3 = Theta1 + H1 * x + K * x2;
+	 Value(Theta3, true, l3, oorg);
+	 if (counter++ > n_it) { TheState = Fail; break; }
+	 if (oorg)
+	 {
+	    if (x <= 1.0)
+	       { x *= 0.5; x2 = x*x; g *= 2.0; d1 *= x; H1 *= x; K *= x2; }
+	    else
+	    {
+	       x = 0.5 * (x-1.0); x2 = x*x; Theta1 = Theta2;
+	       H1 = (H1 + K * 2.0) * x;
+	       K *= x2; g = 0.0; d1 = x * d2; l1 = l2;
+	    }
+	    TheState = Continue; break;
+	 }
+
+	 if (l3 >= l1 && l3 >= l2)
+	    { Theta1 = Theta3; l1 = l3; TheState =  Restart; break; }
+
+	 d3 = LastDerivative(H1 + K * 2.0);
+	 if (l1 > l2)
+	    { H1 *= x; K *= x2; Theta2 = Theta3; d1 *= x; d2 = d3*x; }
+	 else
+	 {
+	    Theta1 = Theta2; Theta2 = Theta3;
+	    x -= 1.0; x2 = x*x; g = 0.0; H1 = (H1 + K * 2.0) * x;
+	    K *= x2; l1 = l2; l2 = l3; d1 = x*d2; d2 = x*d3;
+	    if (d1 <= 0.0) { TheState = Start; break; }
+	 }
+	 TheState =  Interpolate; break;
+
+      case Extrapolate:
+	 tr.ReName("FindMaximum2::Fit/Extrapolate");
+	 Theta1 = Theta2; g = 0.0; K *= 4.0; H1 = (H1 * 2.0 + K);
+	 d1 = 2.0 * d2; l1 = l2;
+	 TheState = Continue; break;
+
+      case Fail:
+	 Throw(ConvergenceException(Theta));
+
+      case Convergence:
+	 Theta = Theta1; return;
+      }
+   }
+}
+
+
+
+void NonLinearLeastSquares::Value
+   (const ColumnVector& Parameters, bool, Real& v, bool& oorg)
+{
+   Tracer tr("NonLinearLeastSquares::Value");
+   Y.ReSize(n_obs); X.ReSize(n_obs,n_param);
+   // put the fitted values in Y, the derivatives in X.
+   Pred.Set(Parameters);
+   if (!Pred.IsValid()) { oorg=true; return; }
+   for (int i=1; i<=n_obs; i++)
+   {
+      Y(i) = Pred(i);
+      X.Row(i) = Pred.Derivatives();
+   }
+   if (!Pred.IsValid()) { oorg=true; return; }  // check afterwards as well
+   Y = *DataPointer - Y; Real ssq = Y.SumSquare();
+   errorvar =  ssq / (n_obs - n_param);
+   cout << endl;
+   cout << setw(15) << setprecision(10) << " " << errorvar;
+   Derivs = Y.t() * X;          // get the derivative and stash it
+   oorg = false; v = -0.5 * ssq;
+}
+
+bool NonLinearLeastSquares::NextPoint(ColumnVector& Adj, Real& test)
+{
+   Tracer tr("NonLinearLeastSquares::NextPoint");
+   QRZ(X, U); QRZ(X, Y, M);     // do the QR decomposition
+   test = M.SumSquare();
+   cout << " " << setw(15) << setprecision(10)
+      << test << " " << Y.SumSquare() / (n_obs - n_param);
+   Adj = U.i() * M;
+   if (test < errorvar * criterion) return true;
+   else return false;
+}
+
+Real NonLinearLeastSquares::LastDerivative(const ColumnVector& H)
+{ return (Derivs * H).AsScalar(); }
+
+void NonLinearLeastSquares::Fit(const ColumnVector& Data,
+   ColumnVector& Parameters)
+{
+   Tracer tr("NonLinearLeastSquares::Fit");
+   n_param = Parameters.Nrows(); n_obs = Data.Nrows();
+   DataPointer = &Data;
+   FindMaximum2::Fit(Parameters, Lim);
+   cout << "\nConverged" << endl;
+}
+
+void NonLinearLeastSquares::MakeCovariance()
+{
+   if (Covariance.Nrows()==0)
+   {
+      UpperTriangularMatrix UI = U.i();
+      Covariance << UI * UI.t() * errorvar;
+      SE << Covariance;                 // get diagonals
+      for (int i = 1; i<=n_param; i++) SE(i) = sqrt(SE(i));
+   }
+}
+
+void NonLinearLeastSquares::GetStandardErrors(ColumnVector& SEX)
+   { MakeCovariance(); SEX = SE.AsColumn(); }
+
+void NonLinearLeastSquares::GetCorrelations(SymmetricMatrix& Corr)
+   { MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); }
+
+void NonLinearLeastSquares::GetHatDiagonal(DiagonalMatrix& Hat) const
+{
+   Hat.ReSize(n_obs);
+   for (int i = 1; i<=n_obs; i++) Hat(i) = X.Row(i).SumSquare();
+}
+
+
+// the MLE_D_FI routines
+
+void MLE_D_FI::Value
+   (const ColumnVector& Parameters, bool wg, Real& v, bool& oorg)
+{
+   Tracer tr("MLE_D_FI::Value");
+   if (!LL.IsValid(Parameters,wg)) { oorg=true; return; }
+   v = LL.LogLikelihood();
+   if (!LL.IsValid()) { oorg=true; return; }     // check validity again
+   cout << endl;
+   cout << setw(20) << setprecision(10) << v;
+   oorg = false;
+   Derivs = LL.Derivatives();                    // Get derivatives
+}
+
+bool MLE_D_FI::NextPoint(ColumnVector& Adj, Real& test)
+{
+   Tracer tr("MLE_D_FI::NextPoint");
+   SymmetricMatrix FI = LL.FI();
+   LT = Cholesky(FI);
+   ColumnVector Adj1 = LT.i() * Derivs;
+   Adj = LT.t().i() * Adj1;
+   test = SumSquare(Adj1);
+   cout << "   " << setw(20) << setprecision(10) << test;
+   return (test < Criterion);
+}
+
+Real MLE_D_FI::LastDerivative(const ColumnVector& H)
+{ return (Derivs.t() * H).AsScalar(); }
+
+void MLE_D_FI::Fit(ColumnVector& Parameters)
+{
+   Tracer tr("MLE_D_FI::Fit");
+   FindMaximum2::Fit(Parameters,Lim);
+   cout << "\nConverged" << endl;
+}
+  
+void MLE_D_FI::MakeCovariance()
+{
+   if (Covariance.Nrows()==0)
+   {
+      LowerTriangularMatrix LTI = LT.i();
+      Covariance << LTI.t() * LTI;
+      SE << Covariance;                // get diagonal
+      int n = Covariance.Nrows();
+      for (int i=1; i <= n; i++) SE(i) = sqrt(SE(i));
+   }
+}
+
+void MLE_D_FI::GetStandardErrors(ColumnVector& SEX)
+{ MakeCovariance(); SEX = SE.AsColumn(); }
+   
+void MLE_D_FI::GetCorrelations(SymmetricMatrix& Corr)
+{ MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); }
+
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/newmatnl.h
===================================================================
RCS file: Shared/newmat/newmatnl.h
diff -N Shared/newmat/newmatnl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatnl.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,322 @@
+//$$ newmatnl.h           definition file for non-linear optimisation
+
+// Copyright (C) 1993,4,5: R B Davies
+
+#ifndef NEWMATNL_LIB
+#define NEWMATNL_LIB 0
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+/*
+
+This is a beginning of a series of classes for non-linear optimisation.
+
+At present there are two classes. FindMaximum2 is the basic optimisation
+strategy when one is doing an optimisation where one has first
+derivatives and estimates of the second derivatives. Class
+NonLinearLeastSquares is derived from FindMaximum2. This provides the
+functions that calculate function values and derivatives.
+
+A third class is now added. This is for doing maximum-likelihood when
+you have first derviatives and something like the Fisher Information
+matrix (eg the variance covariance matrix of the first derivatives or
+minus the second derivatives - this matrix is assumed to be positive
+definite).
+
+
+
+   class FindMaximum2
+
+Suppose T is the ColumnVector of parameters, F(T) the function we want
+to maximise, D(T) the ColumnVector of derivatives of F with respect to
+T, and S(T) the matrix of second derivatives.
+
+Then the basic iteration is given a value of T, update it to
+
+           T - S.i() * D
+
+where .i() denotes inverse.
+
+If F was quadratic this would give exactly the right answer (except it
+might get a minimum rather than a maximum). Since F is not usually
+quadratic, the simple procedure would be to recalculate S and D with the
+new value of T and keep iterating until the process converges. This is
+known as the method of conjugate gradients.
+
+In practice, this method may not converge. FindMaximum2 considers an
+iteration of the form
+
+           T - x * S.i() * D
+
+where x is a number. It tries x = 1 and uses the values of F and its
+slope with respect to x at x = 0 and x = 1 to fit a cubic in x. It then
+choses x to maximise the resulting function. This gives our new value of
+T. The program checks that the value of F is getting better and carries
+out a variety of strategies if it is not.
+
+The program also has a second strategy. If the successive values of T
+seem to be lying along a curve - eg we are following along a curved
+ridge, the program will try to fit this ridge and project along it. This
+does not work at present and is commented out.
+
+FindMaximum2 has three virtual functions which need to be over-ridden by
+a derived class.
+
+   void Value(const ColumnVector& T, bool wg, Real& f, bool& oorg);
+
+T is the column vector of parameters. The function returns the value of
+the function to f, but may instead set oorg to true if the parameter
+values are not valid. If wg is true it may also calculate and store the
+second derivative information.
+
+   bool NextPoint(ColumnVector& H, Real& d);
+
+Using the value of T provided in the previous call of Value, find the
+conjugate gradients adjustment to T, that is - S.i() * D. Also return
+
+           d = D.t() * S.i() * D.
+
+NextPoint should return true if it considers that the process has
+converged (d very small) and false otherwise. The previous call of Value
+will have set wg to true, so that S will be available.
+
+   Real LastDerivative(const ColumnVector& H);
+
+Return the scalar product of H and the vector of derivatives at the last
+value of T.
+
+The function Fit is the function that calls the iteration.
+
+   void Fit(ColumnVector&, int);
+
+The arguments are the trial parameter values as a ColumnVector and the
+maximum number of iterations. The program calls a DataException if the
+initial parameters are not valid and a ConvergenceException if the
+process fails to converge.
+
+
+   class NonLinearLeastSquares
+
+This class is derived from FindMaximum2 and carries out a non-linear
+least squares fit. It uses a QR decomposition to carry out the
+operations required by FindMaximum2.
+
+A prototype class R1_Col_I_D is provided. The user needs to derive a
+class from this which includes functions the predicted value of each
+observation its derivatives. An object from this class has to be
+provided to class NonLinearLeastSquares.
+
+Suppose we observe n normal random variables with the same unknown
+variance and such the i-th one has expected value given by f(i,P)
+where P is a column vector of unknown parameters and f is a known
+function. We wish to estimate P.
+
+First derive a class from R1_Col_I_D and override Real operator()(int i)
+to give the value of the function f in terms of i and the ColumnVector
+para defined in class R1_CoL_I_D. Also override ReturnMatrix
+Derivatives() to give the derivates of f at para and the value of i
+used in the preceeding call to operator(). Return the result as a
+RowVector. Construct an object from this class. Suppose in what follows
+it is called pred.
+
+Now constuct a NonLinearLeastSquaresObject accessing pred and optionally
+an iteration limit and an accuracy critierion.
+
+   NonLinearLeastSquares NLLS(pred, 1000, 0.0001);
+
+The accuracy critierion should be somewhat less than one and 0.0001 is
+about the smallest sensible value.
+
+Define a ColumnVector P containing a guess at the value of the unknown
+parameter, and a ColumnVector Y containing the unknown data. Call
+
+   NLLS.Fit(Y,P);
+
+If the process converges, P will contain the estimates of the unknown
+parameters. If it does not converge an exception will be generated.
+
+The following member functions can be called after you have done a fit.
+
+Real ResidualVariance() const;
+
+The estimate of the variance of the observations.
+
+void GetResiduals(ColumnVector& Z) const;
+
+The residuals of the individual observations.
+
+void GetStandardErrors(ColumnVector&);
+
+The standard errors of the observations.
+
+void GetCorrelations(SymmetricMatrix&);
+
+The correlations of the observations.
+
+void GetHatDiagonal(DiagonalMatrix&) const;
+
+Forms a diagonal matrix of values between 0 and 1. If the i-th value is
+larger than, say 0.2, then the i-th data value could have an undue
+influence on your estimates.
+
+
+*/
+
+class FindMaximum2
+{
+   virtual void Value(const ColumnVector&, bool, Real&, bool&) = 0;
+   virtual bool NextPoint(ColumnVector&, Real&) = 0;
+   virtual Real LastDerivative(const ColumnVector&) = 0;
+public:
+   void Fit(ColumnVector&, int);
+   virtual ~FindMaximum2() {}            // to keep gnu happy
+};
+
+class R1_Col_I_D
+{
+   // The prototype for a Real function of a ColumnVector and an
+   // integer.
+   // You need to derive your function from this one and put in your
+   // function for operator() and Derivatives() at least.
+   // You may also want to set up a constructor to enter in additional
+   // parameter values (that will not vary during the solve).
+
+protected:
+   ColumnVector para;                 // Current x value
+
+public:
+   virtual bool IsValid() { return true; }
+                                       // is the current x value OK
+   virtual Real operator()(int i) = 0; // i-th function value at current para
+   virtual void Set(const ColumnVector& X) { para = X; }
+                                       // set current para
+   bool IsValid(const ColumnVector& X)
+      { Set(X); return IsValid(); }
+                                       // set para, check OK
+   Real operator()(int i, const ColumnVector& X)
+      { Set(X); return operator()(i); }
+                                       // set para, return value
+   virtual ReturnMatrix Derivatives() = 0;
+                                       // return derivatives as RowVector
+   virtual ~R1_Col_I_D() {}            // to keep gnu happy
+};
+
+
+class NonLinearLeastSquares : public FindMaximum2
+{
+   // these replace the corresponding functions in FindMaximum2
+   void Value(const ColumnVector&, bool, Real&, bool&);
+   bool NextPoint(ColumnVector&, Real&);
+   Real LastDerivative(const ColumnVector&);
+
+   Matrix X;                         // the things we need to do the
+   ColumnVector Y;                   // QR triangularisation
+   UpperTriangularMatrix U;          // see the write-up in newmata.txt
+   ColumnVector M;
+   Real errorvar, criterion;
+   int n_obs, n_param;
+   const ColumnVector* DataPointer;
+   RowVector Derivs;
+   SymmetricMatrix Covariance;
+   DiagonalMatrix SE;
+   R1_Col_I_D& Pred;                 // Reference to predictor object
+   int Lim;                          // maximum number of iterations
+
+public:
+   NonLinearLeastSquares(R1_Col_I_D& pred, int lim=1000, Real crit=0.0001)
+      : criterion(crit), Pred(pred), Lim(lim) {}
+   void Fit(const ColumnVector&, ColumnVector&);
+   Real ResidualVariance() const { return errorvar; }
+   void GetResiduals(ColumnVector& Z) const { Z = Y; }
+   void GetStandardErrors(ColumnVector&);
+   void GetCorrelations(SymmetricMatrix&);
+   void GetHatDiagonal(DiagonalMatrix&) const;
+
+private:
+   void MakeCovariance();
+};
+
+
+// The next class is the prototype class for calculating the
+// log-likelihood.
+// I assume first derivatives are available and something like the 
+// Fisher Information or variance/covariance matrix of the first
+// derivatives or minus the matrix of second derivatives is
+// available. This matrix must be positive definite.
+
+class LL_D_FI
+{
+protected:
+   ColumnVector para;                  // current parameter values
+   bool wg;                         // true if FI matrix wanted
+
+public:
+   virtual void Set(const ColumnVector& X) { para = X; }
+                                       // set parameter values
+   virtual void WG(bool wgx) { wg = wgx; }
+                                       // set wg
+
+   virtual bool IsValid() { return true; }
+                                       // return true is para is OK
+   bool IsValid(const ColumnVector& X, bool wgx=true)
+      { Set(X); WG(wgx); return IsValid(); }
+
+   virtual Real LogLikelihood() = 0;   // return the loglikelihhod
+   Real LogLikelihood(const ColumnVector& X, bool wgx=true)
+      { Set(X); WG(wgx); return LogLikelihood(); }
+
+   virtual ReturnMatrix Derivatives() = 0;
+                                       // column vector of derivatives
+   virtual ReturnMatrix FI() = 0;      // Fisher Information matrix
+   virtual ~LL_D_FI() {}               // to keep gnu happy
+};
+
+// This is the class for doing the maximum likelihood estimation
+
+class MLE_D_FI : public FindMaximum2
+{
+   // these replace the corresponding functions in FindMaximum2
+   void Value(const ColumnVector&, bool, Real&, bool&);
+   bool NextPoint(ColumnVector&, Real&);
+   Real LastDerivative(const ColumnVector&);
+
+   // the things we need for the analysis
+   LL_D_FI& LL;                        // reference to log-likelihood
+   int Lim;                            // maximum number of iterations
+   Real Criterion;                     // convergence criterion
+   ColumnVector Derivs;                // for the derivatives
+   LowerTriangularMatrix LT;           // Cholesky decomposition of FI
+   SymmetricMatrix Covariance;
+   DiagonalMatrix SE;
+
+public:
+   MLE_D_FI(LL_D_FI& ll, int lim=1000, Real criterion=0.0001)
+      : LL(ll), Lim(lim), Criterion(criterion) {}
+   void Fit(ColumnVector& Parameters);
+   void GetStandardErrors(ColumnVector&);
+   void GetCorrelations(SymmetricMatrix&);
+
+private:
+   void MakeCovariance();
+};
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
+
+// body file: newmatnl.cpp
+
+
+
+
Index: Shared/newmat/newmatrc.h
===================================================================
RCS file: Shared/newmat/newmatrc.h
diff -N Shared/newmat/newmatrc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatrc.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,171 @@
+//$$ newmatrc.h              definition file for row/column classes
+
+// Copyright (C) 1991,2,3,4,7: R B Davies
+
+#ifndef NEWMATRC_LIB
+#define NEWMATRC_LIB 0
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#include "controlw.h"
+
+
+/************** classes MatrixRowCol, MatrixRow, MatrixCol *****************/
+
+// Used for accessing the rows and columns of matrices
+// All matrix classes must provide routines for calculating matrix rows and
+// columns. Assume rows can be found very efficiently.
+
+enum LSF { LoadOnEntry=1,StoreOnExit=2,DirectPart=4,StoreHere=8,HaveStore=16 };
+
+
+class LoadAndStoreFlag : public ControlWord
+{
+public:
+   LoadAndStoreFlag() {}
+   LoadAndStoreFlag(int i) : ControlWord(i) {}
+   LoadAndStoreFlag(LSF lsf) : ControlWord(lsf) {}
+   LoadAndStoreFlag(const ControlWord& cwx) : ControlWord(cwx) {}
+};
+
+class MatrixRowCol
+// the row or column of a matrix
+{
+public:                                        // these are public to avoid
+                                               // numerous friend statements
+   int length;                                 // row or column length
+   int skip;                                   // initial number of zeros
+   int storage;                                // number of stored elements
+   int rowcol;                                 // row or column number
+   GeneralMatrix* gm;                          // pointer to parent matrix
+   Real* data;                                 // pointer to local storage
+   LoadAndStoreFlag cw;                        // Load? Store? Is a Copy?
+   void IncrMat() { rowcol++; data += storage; }   // used by NextRow
+   void IncrDiag() { rowcol++; skip++; data++; }
+   void IncrId() { rowcol++; skip++; }
+   void IncrUT() { rowcol++; data += storage; storage--; skip++; }
+   void IncrLT() { rowcol++; data += storage; storage++; }
+
+public:
+   void Zero();                                // set elements to zero
+   void Add(const MatrixRowCol&);              // add a row/col
+   void AddScaled(const MatrixRowCol&, Real);  // add a multiple of a row/col
+   void Add(const MatrixRowCol&, const MatrixRowCol&);
+                                               // add two rows/cols
+   void Add(const MatrixRowCol&, Real);        // add a row/col
+   void NegAdd(const MatrixRowCol&, Real);     // Real - a row/col
+   void Sub(const MatrixRowCol&);              // subtract a row/col
+   void Sub(const MatrixRowCol&, const MatrixRowCol&);
+					       // sub a row/col from another
+   void RevSub(const MatrixRowCol&);           // subtract from a row/col
+   void ConCat(const MatrixRowCol&, const MatrixRowCol&);
+                                               // concatenate two row/cols
+   void Multiply(const MatrixRowCol&);         // multiply a row/col
+   void Multiply(const MatrixRowCol&, const MatrixRowCol&);
+                                               // multiply two row/cols
+   void KP(const MatrixRowCol&, const MatrixRowCol&);
+                                               // Kronecker Product two row/cols
+   void Copy(const MatrixRowCol&);             // copy a row/col
+   void CopyCheck(const MatrixRowCol&);        // ... check for data loss
+   void Check(const MatrixRowCol&);            // just check for data loss
+   void Check();                               // check full row/col present
+   void Copy(const Real*&);                    // copy from an array
+   void Copy(const int*&);                     // copy from an array
+   void Copy(Real);                            // copy from constant
+   void Add(Real);                             // add a constant
+   void Multiply(Real);                        // multiply by constant
+   Real SumAbsoluteValue();                    // sum of absolute values
+   Real MaximumAbsoluteValue1(Real r, int& i); // maximum of absolute values
+   Real MinimumAbsoluteValue1(Real r, int& i); // minimum of absolute values
+   Real Maximum1(Real r, int& i);              // maximum
+   Real Minimum1(Real r, int& i);              // minimum
+   Real Sum();                                 // sum of values
+   void Inject(const MatrixRowCol&);           // copy stored els of a row/col
+   void Negate(const MatrixRowCol&);           // change sign of a row/col
+   void Multiply(const MatrixRowCol&, Real);   // scale a row/col
+   friend Real DotProd(const MatrixRowCol&, const MatrixRowCol&);
+                                               // sum of pairwise product
+   Real* Data() { return data; }
+   int Skip() { return skip; }                 // number of elements skipped
+   int Storage() { return storage; }           // number of elements stored
+   int Length() { return length; }             // length of row or column
+   void Skip(int i) { skip=i; }
+   void Storage(int i) { storage=i; }
+   void Length(int i) { length=i; }
+   void SubRowCol(MatrixRowCol&, int, int) const;
+					       // get part of a row or column
+   MatrixRowCol() {}                           // to stop warning messages
+   ~MatrixRowCol();
+   FREE_CHECK(MatrixRowCol)
+};
+
+class MatrixRow : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixRow(GeneralMatrix*, LoadAndStoreFlag, int=0);
+                                               // extract a row
+   ~MatrixRow();
+   void Next();                                // get next row
+   FREE_CHECK(MatrixRow)
+};
+
+class MatrixCol : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixCol(GeneralMatrix*, LoadAndStoreFlag, int=0);
+                                               // extract a col
+   MatrixCol(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
+                                               // store/retrieve a col
+   ~MatrixCol();
+   void Next();                                // get next row
+   FREE_CHECK(MatrixCol)
+};
+
+// MatrixColX is an alternative to MatrixCol where the complete
+// column is stored externally
+
+class MatrixColX : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixColX(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
+                                               // store/retrieve a col
+   ~MatrixColX();
+   void Next();                                // get next row
+   Real* store;                                // pointer to local storage
+                                               //    less skip
+   FREE_CHECK(MatrixColX)
+};
+
+/**************************** inline bodies ****************************/
+
+inline MatrixRow::MatrixRow(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int row)
+{ gm=gmx; cw=cwx; rowcol=row; gm->GetRow(*this); }
+
+inline void MatrixRow::Next() { gm->NextRow(*this); }
+
+inline MatrixCol::MatrixCol(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int col)
+{ gm=gmx; cw=cwx; rowcol=col; gm->GetCol(*this); }
+
+inline MatrixCol::MatrixCol(GeneralMatrix* gmx, Real* r,
+   LoadAndStoreFlag cwx, int col)
+{ gm=gmx; data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
+
+inline MatrixColX::MatrixColX(GeneralMatrix* gmx, Real* r,
+   LoadAndStoreFlag cwx, int col)
+{ gm=gmx; store=data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
+
+
+inline void MatrixCol::Next() { gm->NextCol(*this); }
+
+inline void MatrixColX::Next() { gm->NextCol(*this); }
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
Index: Shared/newmat/newmatrm.cpp
===================================================================
RCS file: Shared/newmat/newmatrm.cpp
diff -N Shared/newmat/newmatrm.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatrm.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,216 @@
+//$$newmatrm.cpp                         rectangular matrix operations
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "newmat.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,12); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+// operations on rectangular matrices
+
+
+void RectMatrixRow::Reset (const Matrix& M, int row, int skip, int length)
+{
+   REPORT
+   RectMatrixRowCol::Reset
+      ( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() );
+}
+
+void RectMatrixRow::Reset (const Matrix& M, int row)
+{
+   REPORT
+   RectMatrixRowCol::Reset( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() );
+}
+
+void RectMatrixCol::Reset (const Matrix& M, int skip, int col, int length)
+{
+   REPORT
+   RectMatrixRowCol::Reset
+      ( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 );
+}
+
+void RectMatrixCol::Reset (const Matrix& M, int col)
+{
+   REPORT
+   RectMatrixRowCol::Reset( M.Store()+col, M.Nrows(), M.Ncols(), 1 );
+}
+
+
+Real RectMatrixRowCol::SumSquare() const
+{
+   REPORT
+   long_Real sum = 0.0; int i = n; Real* s = store; int d = spacing;
+   // while (i--) { sum += (long_Real)*s * *s; s += d; }
+   if (i) for(;;)
+      { sum += (long_Real)*s * *s; if (!(--i)) break; s += d; }
+   return (Real)sum;
+}
+
+Real RectMatrixRowCol::operator*(const RectMatrixRowCol& rmrc) const
+{
+   REPORT
+   long_Real sum = 0.0; int i = n;
+   Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in *"));
+   }
+   // while (i--) { sum += (long_Real)*s * *s1; s += d; s1 += d1; }
+   if (i) for(;;)
+      { sum += (long_Real)*s * *s1; if (!(--i)) break; s += d; s1 += d1; }
+   return (Real)sum;
+}
+
+void RectMatrixRowCol::AddScaled(const RectMatrixRowCol& rmrc, Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in AddScaled"));
+   }
+   // while (i--) { *s += *s1 * r; s += d; s1 += d1; }
+   if (i) for (;;)
+      { *s += *s1 * r; if (!(--i)) break; s += d; s1 += d1; }
+}
+
+void RectMatrixRowCol::Divide(const RectMatrixRowCol& rmrc, Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in Divide"));
+   }
+   // while (i--) { *s = *s1 / r; s += d; s1 += d1; }
+   if (i) for (;;) { *s = *s1 / r; if (!(--i)) break; s += d; s1 += d1; }
+}
+
+void RectMatrixRowCol::Divide(Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s /= r; s += d; }
+   if (i) for (;;) { *s /= r; if (!(--i)) break; s += d; }
+}
+
+void RectMatrixRowCol::Negate()
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s = - *s; s += d; }
+   if (i) for (;;) { *s = - *s; if (!(--i)) break; s += d; }
+}
+
+void RectMatrixRowCol::Zero()
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s = 0.0; s += d; }
+   if (i) for (;;) { *s = 0.0; if (!(--i)) break; s += d; }
+}
+
+void ComplexScale(RectMatrixCol& U, RectMatrixCol& V, Real x, Real y)
+{
+   REPORT
+   int n = U.n;
+   if (n != V.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in ComplexScale"));
+   }
+   Real* u = U.store; Real* v = V.store; 
+   int su = U.spacing; int sv = V.spacing;
+   //while (n--)
+   //{
+   //   Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
+   //   u += su;  v += sv;
+   //}
+   if (n) for (;;)
+   {
+      Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
+      if (!(--n)) break;
+      u += su;  v += sv;
+   }
+}
+
+void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s)
+{
+   REPORT
+   //  (U, V) = (U, V) * (c, s)  where  tau = s/(1+c), c^2 + s^2 = 1
+   int n = U.n;
+   if (n != V.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in Rotate"));
+   }
+   Real* u = U.store; Real* v = V.store;
+   int su = U.spacing; int sv = V.spacing;
+   //while (n--)
+   //{
+   //   Real zu = *u; Real zv = *v;
+   //   *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
+   //   u += su;  v += sv;
+   //}
+   if (n) for(;;)
+   {
+      Real zu = *u; Real zv = *v;
+      *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
+      if (!(--n)) break;
+      u += su;  v += sv;
+   }
+}
+
+
+// misc procedures for numerical things
+
+Real pythag(Real f, Real g, Real& c, Real& s)
+// return z=sqrt(f*f+g*g), c=f/z, s=g/z
+// set c=1,s=0 if z==0
+// avoid floating point overflow or divide by zero
+{
+   if (f==0 && g==0) { c=1.0; s=0.0; return 0.0; }
+   Real af = f>=0 ? f : -f;
+   Real ag = g>=0 ? g : -g;
+   if (ag<af)
+   {
+      REPORT
+      Real h = g/f; Real sq = sqrt(1.0+h*h);
+      if (f<0) sq = -sq;           // make return value non-negative
+      c = 1.0/sq; s = h/sq; return sq*f;
+   }
+   else
+   {
+      REPORT
+      Real h = f/g; Real sq = sqrt(1.0+h*h);
+      if (g<0) sq = -sq;
+      s = 1.0/sq; c = h/sq; return sq*g;
+   }
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
Index: Shared/newmat/newmatrm.h
===================================================================
RCS file: Shared/newmat/newmatrm.h
diff -N Shared/newmat/newmatrm.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/newmatrm.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,145 @@
+//$$newmatrm.h                            rectangular matrix operations
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#ifndef NEWMATRM_LIB
+#define NEWMATRM_LIB 0
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+// operations on rectangular matrices
+
+class RectMatrixCol;
+
+class RectMatrixRowCol
+// a class for accessing rows and columns of rectangular matrices
+{
+protected:
+#ifdef use_namespace              // to make namespace work
+public:
+#endif
+   Real* store;                   // pointer to storage
+   int n;                         // number of elements
+   int spacing;                   // space between elements
+   int shift;                     // space between cols or rows
+   RectMatrixRowCol(Real* st, int nx, int sp, int sh)
+      : store(st), n(nx), spacing(sp), shift(sh) {}
+   void Reset(Real* st, int nx, int sp, int sh)
+      { store=st; n=nx; spacing=sp; shift=sh; }
+public:
+   Real operator*(const RectMatrixRowCol&) const;         // dot product
+   void AddScaled(const RectMatrixRowCol&, Real);         // add scaled
+   void Divide(const RectMatrixRowCol&, Real);            // scaling
+   void Divide(Real);                                     // scaling
+   void Negate();                                         // change sign
+   void Zero();                                           // zero row col
+   Real& operator[](int i) { return *(store+i*spacing); } // element
+   Real SumSquare() const;                                // sum of squares
+   Real& First() { return *store; }                       // get first element
+   void DownDiag() { store += (shift+spacing); n--; }
+   void UpDiag() { store -= (shift+spacing); n++; }
+   friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   FREE_CHECK(RectMatrixRowCol)
+};
+
+class RectMatrixRow : public RectMatrixRowCol
+{
+public:
+   RectMatrixRow(const Matrix&, int, int, int);
+   RectMatrixRow(const Matrix&, int);
+   void Reset(const Matrix&, int, int, int);
+   void Reset(const Matrix&, int);
+   Real& operator[](int i) { return *(store+i); }
+   void Down() { store += shift; }
+   void Right() { store++; n--; }
+   void Up() { store -= shift; }
+   void Left() { store--; n++; }
+   FREE_CHECK(RectMatrixRow)
+};
+
+class RectMatrixCol : public RectMatrixRowCol
+{
+public:
+   RectMatrixCol(const Matrix&, int, int, int);
+   RectMatrixCol(const Matrix&, int);
+   void Reset(const Matrix&, int, int, int);
+   void Reset(const Matrix&, int);
+   void Down() { store += spacing; n--; }
+   void Right() { store++; }
+   void Up() { store -= spacing; n++; }
+   void Left() { store--; }
+   friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   FREE_CHECK(RectMatrixCol)
+};
+
+class RectMatrixDiag : public RectMatrixRowCol
+{
+public:
+   RectMatrixDiag(const DiagonalMatrix& D)
+      : RectMatrixRowCol(D.Store(), D.Nrows(), 1, 1) {}
+   Real& operator[](int i) { return *(store+i); }
+   void DownDiag() { store++; n--; }
+   void UpDiag() { store--; n++; }
+   FREE_CHECK(RectMatrixDiag)
+};
+
+
+
+
+inline RectMatrixRow::RectMatrixRow
+   (const Matrix& M, int row, int skip, int length)
+   : RectMatrixRowCol( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() ) {}
+
+inline RectMatrixRow::RectMatrixRow (const Matrix& M, int row)
+   : RectMatrixRowCol( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() ) {}
+
+inline RectMatrixCol::RectMatrixCol
+   (const Matrix& M, int skip, int col, int length)
+   : RectMatrixRowCol( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 ) {}
+
+inline RectMatrixCol::RectMatrixCol (const Matrix& M, int col)
+   : RectMatrixRowCol( M.Store()+col, M.Nrows(), M.Ncols(), 1 ) {}
+
+inline Real square(Real x) { return x*x; }
+inline Real sign(Real x, Real y)
+   { return (y>=0) ? x : -x; }                    // assume x >=0
+
+
+// Misc numerical things
+
+Real pythag(Real f, Real g, Real& c, Real& s);
+
+inline void GivensRotation(Real cGivens, Real sGivens, Real& x, Real& y)
+{
+   // allow for possibility &x = &y
+   Real tmp0 = cGivens * x + sGivens * y;
+   Real tmp1 = -sGivens * x + cGivens * y;
+   x = tmp0; y = tmp1;
+}
+   
+inline void GivensRotationR(Real cGivens, Real sGivens, Real& x, Real& y)
+{
+   // also change sign of y
+   // allow for possibility &x = &y
+   Real tmp0 = cGivens * x + sGivens * y;
+   Real tmp1 = sGivens * x - cGivens * y;
+   x = tmp0; y = tmp1;
+}   
+
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+// body file: newmatrm.cpp
+
+
Index: Shared/newmat/precisio.h
===================================================================
RCS file: Shared/newmat/precisio.h
diff -N Shared/newmat/precisio.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/precisio.h	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,241 @@
+//$$ precisio.h                          floating point constants
+
+#ifndef PRECISION_LIB
+#define PRECISION_LIB 0
+
+#ifdef _STANDARD_                 // standard library available
+#include <limits>
+#endif
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef _STANDARD_                 // standard library available
+
+using namespace std;
+	
+class FloatingPointPrecision
+{
+public:
+   static int Dig()              // number of decimal digits or precision
+      { return numeric_limits<Real>::digits10 ; }
+
+   static Real Epsilon()         // smallest number such that 1+Eps!=Eps
+      { return numeric_limits<Real>::epsilon(); }
+
+   static int Mantissa()         // bits in mantisa
+      { return numeric_limits<Real>::digits; }
+
+   static Real Maximum()         // maximum value
+      { return numeric_limits<Real>::max(); }
+
+   static int MaximumDecimalExponent()  // maximum decimal exponent
+      { return numeric_limits<Real>::max_exponent10; }
+
+   static int MaximumExponent()  // maximum binary exponent
+      { return numeric_limits<Real>::max_exponent; }
+
+   static Real LnMaximum()       // natural log of maximum
+      { return (Real)log(Maximum()); }
+
+   static Real Minimum()         // minimum positive value
+      { return numeric_limits<Real>::min(); } 
+
+   static int MinimumDecimalExponent() // minimum decimal exponent
+      { return numeric_limits<Real>::min_exponent10; }
+
+   static int MinimumExponent()  // minimum binary exponent
+      { return numeric_limits<Real>::min_exponent; }
+
+   static Real LnMinimum()       // natural log of minimum
+      { return (Real)log(Minimum()); }
+
+   static int Radix()            // exponent radix
+      { return numeric_limits<Real>::radix; }
+
+   static int Rounds()           // addition rounding (1 = does round)
+   {
+	  return numeric_limits<Real>::round_style ==
+		 round_to_nearest ? 1 : 0;
+   }
+
+};
+
+
+#else                              // _STANDARD_ not defined
+
+#ifndef SystemV                    // if there is float.h
+
+
+#ifdef USING_FLOAT
+
+
+class FloatingPointPrecision
+{
+public:
+   static int Dig()
+      { return FLT_DIG; }        // number of decimal digits or precision
+
+   static Real Epsilon()
+      { return FLT_EPSILON; }    // smallest number such that 1+Eps!=Eps
+
+   static int Mantissa()
+      { return FLT_MANT_DIG; }   // bits in mantisa
+
+   static Real Maximum()
+      { return FLT_MAX; }        // maximum value
+
+   static int MaximumDecimalExponent()
+      { return FLT_MAX_10_EXP; } // maximum decimal exponent
+
+   static int MaximumExponent()
+      { return FLT_MAX_EXP; }    // maximum binary exponent
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); } // natural log of maximum
+
+   static Real Minimum()
+      { return FLT_MIN; }        // minimum positive value
+
+   static int MinimumDecimalExponent()
+      { return FLT_MIN_10_EXP; } // minimum decimal exponent
+
+   static int MinimumExponent()
+      { return FLT_MIN_EXP; }    // minimum binary exponent
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); } // natural log of minimum
+
+   static int Radix()
+      { return FLT_RADIX; }      // exponent radix
+
+   static int Rounds()
+      { return FLT_ROUNDS; }     // addition rounding (1 = does round)
+
+};
+
+#endif                           // USING_FLOAT
+
+
+#ifdef USING_DOUBLE
+
+class FloatingPointPrecision
+{
+public:
+
+   static int Dig()
+      { return DBL_DIG; }        // number of decimal digits or precision
+
+   static Real Epsilon()
+      { return DBL_EPSILON; }    // smallest number such that 1+Eps!=Eps
+
+   static int Mantissa()
+      { return DBL_MANT_DIG; }   // bits in mantisa
+
+   static Real Maximum()
+      { return DBL_MAX; }        // maximum value
+
+   static int MaximumDecimalExponent()
+      { return DBL_MAX_10_EXP; } // maximum decimal exponent
+
+   static int MaximumExponent()
+      { return DBL_MAX_EXP; }    // maximum binary exponent
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); } // natural log of maximum
+
+   static Real Minimum()
+   {
+//#ifdef __BCPLUSPLUS__
+//       return 2.225074e-308;     // minimum positive value
+//#else
+       return DBL_MIN;
+//#endif
+   }
+
+   static int MinimumDecimalExponent()
+      { return DBL_MIN_10_EXP; } // minimum decimal exponent
+
+   static int MinimumExponent()
+      { return DBL_MIN_EXP; }    // minimum binary exponent
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); } // natural log of minimum
+
+
+   static int Radix()
+      { return FLT_RADIX; }      // exponent radix
+
+   static int Rounds()
+      { return FLT_ROUNDS; }     // addition rounding (1 = does round)
+
+};
+
+#endif                             // USING_DOUBLE
+
+#else                              // if there is no float.h
+
+#ifdef USING_FLOAT
+
+class FloatingPointPrecision
+{
+public:
+
+   static Real Epsilon()
+      { return pow(2.0,(int)(1-FSIGNIF)); }
+                                   // smallest number such that 1+Eps!=Eps
+
+   static Real Maximum()
+      { return MAXFLOAT; }            // maximum value
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); }  // natural log of maximum
+
+   static Real Minimum()
+      { return MINFLOAT; }             // minimum positive value
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); }  // natural log of minimum
+
+};
+
+#endif                                  // USING_FLOAT
+
+
+#ifdef USING_DOUBLE
+
+class FloatingPointPrecision
+{
+public:
+
+   static Real Epsilon()
+      { return pow(2.0,(int)(1-DSIGNIF)); }
+                                      // smallest number such that 1+Eps!=Eps
+
+   static Real Maximum()
+      { return MAXDOUBLE; }           // maximum value
+
+   static Real LnMaximum()
+      { return LN_MAXDOUBLE; }        // natural log of maximum
+
+   static Real Minimum()
+      { return MINDOUBLE; }
+
+   static Real LnMinimum()
+      { return LN_MINDOUBLE; }        // natural log of minimum
+};
+
+#endif                                // USING_DOUBLE
+
+#endif                                // SystemV
+
+#endif                                // _STANDARD_
+
+#ifdef use_namespace
+}
+#endif                                // use_namespace
+
+
+
+#endif                                // PRECISION_LIB
Index: Shared/newmat/readme.txt
===================================================================
RCS file: Shared/newmat/readme.txt
diff -N Shared/newmat/readme.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/readme.txt	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,12 @@
+ReadMe file for newmat11 - beta version - 28 March, 2004
+-------------------------------------------------------------
+
+This is a beta version of newmat11.
+
+Documentation is in nm11.htm.
+
+This library is freeware and may be freely used and distributed.
+
+To contact the author please email robert@statsresearch.co.nz
+
+
Index: Shared/newmat/sort.cpp
===================================================================
RCS file: Shared/newmat/sort.cpp
diff -N Shared/newmat/sort.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/sort.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,272 @@
+//$$ sort.cpp                            Sorting
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,13); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/******************************** Quick sort ********************************/
+
+// Quicksort.
+// Essentially the method described in Sedgewick s algorithms in C++
+// My version is still partially recursive, unlike Segewick s, but the
+// smallest segment of each split is used in the recursion, so it should
+// not overlead the stack.
+
+// If the process does not seems to be converging an exception is thrown.
+
+
+#define DoSimpleSort 17            // when to switch to insert sort
+#define MaxDepth 50                // maximum recursion depth
+
+static void MyQuickSortDescending(Real* first, Real* last, int depth);
+static void InsertionSortDescending(Real* first, const int length,
+   int guard);
+static Real SortThreeDescending(Real* a, Real* b, Real* c);
+
+static void MyQuickSortAscending(Real* first, Real* last, int depth);
+static void InsertionSortAscending(Real* first, const int length,
+   int guard);
+
+
+void SortDescending(GeneralMatrix& GM)
+{
+   REPORT
+   Tracer et("QuickSortDescending");
+
+   Real* data = GM.Store(); int max = GM.Storage();
+
+   if (max > DoSimpleSort) MyQuickSortDescending(data, data + max - 1, 0);
+   InsertionSortDescending(data, max, DoSimpleSort);
+
+}
+
+static Real SortThreeDescending(Real* a, Real* b, Real* c)
+{
+   // sort *a, *b, *c; return *b; optimise for already sorted
+   if (*a >= *b)
+   {
+      if (*b >= *c) { REPORT return *b; }
+      else if (*a >= *c) { REPORT Real x = *c; *c = *b; *b = x; return x; }
+      else { REPORT Real x = *a; *a = *c; *c = *b; *b = x; return x; }
+   }
+   else if (*c >= *b) { REPORT Real x = *c; *c = *a; *a = x; return *b; }
+   else if (*a >= *c) { REPORT Real x = *a; *a = *b; *b = x; return x; }
+   else { REPORT Real x = *c; *c = *a; *a = *b; *b = x; return x; }
+}
+
+static void InsertionSortDescending(Real* first, const int length,
+   int guard)
+// guard gives the length of the sequence to scan to find first
+// element (eg = length)
+{
+   REPORT
+   if (length <= 1) return;
+
+   // scan for first element
+   Real* f = first; Real v = *f; Real* h = f;
+   if (guard > length) { REPORT guard = length; }
+   int i = guard - 1;
+   while (i--) if (v < *(++f)) { v = *f; h = f; }
+   *h = *first; *first = v;
+
+   // do the sort
+   i = length - 1; f = first;
+   while (i--)
+   {
+      Real* g = f++; h = f; v = *h;
+      while (*g < v) *h-- = *g--;
+      *h = v;
+   }
+}
+
+static void MyQuickSortDescending(Real* first, Real* last, int depth)
+{
+   REPORT
+   for (;;)
+   {
+      const int length = last - first + 1;
+      if (length < DoSimpleSort) { REPORT return; }
+      if (depth++ > MaxDepth)
+         Throw(ConvergenceException("QuickSortDescending fails: "));
+      Real* centre = first + length/2;
+      const Real test = SortThreeDescending(first, centre, last);
+      Real* f = first; Real* l = last;
+      for (;;)
+      {
+         while (*(++f) > test) {}
+         while (*(--l) < test) {}
+         if (l <= f) break;
+         const Real temp = *f; *f = *l; *l = temp;
+      }
+      if (f > centre)
+         { REPORT MyQuickSortDescending(l+1, last, depth); last = f-1; }
+      else { REPORT MyQuickSortDescending(first, f-1, depth); first = l+1; }
+   }
+}
+
+void SortAscending(GeneralMatrix& GM)
+{
+   REPORT
+   Tracer et("QuickSortAscending");
+
+   Real* data = GM.Store(); int max = GM.Storage();
+
+   if (max > DoSimpleSort) MyQuickSortAscending(data, data + max - 1, 0);
+   InsertionSortAscending(data, max, DoSimpleSort);
+
+}
+
+static void InsertionSortAscending(Real* first, const int length,
+   int guard)
+// guard gives the length of the sequence to scan to find first
+// element (eg guard = length)
+{
+   REPORT
+   if (length <= 1) return;
+
+   // scan for first element
+   Real* f = first; Real v = *f; Real* h = f;
+   if (guard > length) { REPORT guard = length; }
+   int i = guard - 1;
+   while (i--) if (v > *(++f)) { v = *f; h = f; }
+   *h = *first; *first = v;
+
+   // do the sort
+   i = length - 1; f = first;
+   while (i--)
+   {
+      Real* g = f++; h = f; v = *h;
+      while (*g > v) *h-- = *g--;
+      *h = v;
+   }
+}
+static void MyQuickSortAscending(Real* first, Real* last, int depth)
+{
+   REPORT
+   for (;;)
+   {
+      const int length = last - first + 1;
+      if (length < DoSimpleSort) { REPORT return; }
+      if (depth++ > MaxDepth)
+         Throw(ConvergenceException("QuickSortAscending fails: "));
+      Real* centre = first + length/2;
+      const Real test = SortThreeDescending(last, centre, first);
+      Real* f = first; Real* l = last;
+      for (;;)
+      {
+         while (*(++f) < test) {}
+         while (*(--l) > test) {}
+         if (l <= f) break;
+         const Real temp = *f; *f = *l; *l = temp;
+      }
+      if (f > centre)
+         { REPORT MyQuickSortAscending(l+1, last, depth); last = f-1; }
+      else { REPORT MyQuickSortAscending(first, f-1, depth); first = l+1; }
+   }
+}
+
+//********* sort diagonal matrix & rearrange matrix columns ****************
+
+// used by SVD
+
+// these are for sorting singular values - should be updated with faster
+// sorts that handle exchange of columns better
+// however time is probably not significant compared with SVD time
+
+void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending)
+{
+   REPORT
+   Tracer trace("SortSV_DU");
+   int m = U.Nrows(); int n = U.Ncols();
+   if (n != D.Nrows()) Throw(IncompatibleDimensionsException(D,U));
+   Real* u = U.Store();
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      if (ascending)
+      {
+         for (int j=i+1; j<n; j++)
+            { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      }
+      else
+      {
+         for (int j=i+1; j<n; j++)
+         { if (D.element(j) > p) { k = j; p = D.element(j); } }
+      }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p; int j = m;
+         Real* uji = u + i; Real* ujk = u + k;
+         if (j) for(;;)
+         {
+            p = *uji; *uji = *ujk; *ujk = p;
+            if (!(--j)) break;
+            uji += n; ujk += n;
+         }
+      }
+   }
+}
+
+void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending)
+{
+   REPORT
+   Tracer trace("SortSV_DUV");
+   int mu = U.Nrows(); int mv = V.Nrows(); int n = D.Nrows();
+   if (n != U.Ncols()) Throw(IncompatibleDimensionsException(D,U));
+   if (n != V.Ncols()) Throw(IncompatibleDimensionsException(D,V));
+   Real* u = U.Store(); Real* v = V.Store();
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      if (ascending)
+      {
+         for (int j=i+1; j<n; j++)
+            { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      }
+      else
+      {
+         for (int j=i+1; j<n; j++)
+         { if (D.element(j) > p) { k = j; p = D.element(j); } }
+      }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p;
+         Real* uji = u + i; Real* ujk = u + k;
+         Real* vji = v + i; Real* vjk = v + k;
+         int j = mu;
+         if (j) for(;;)
+         {
+            p = *uji; *uji = *ujk; *ujk = p; if (!(--j)) break;
+            uji += n; ujk += n;
+         }
+         j = mv;
+         if (j) for(;;)
+         {
+            p = *vji; *vji = *vjk; *vjk = p; if (!(--j)) break;
+            vji += n; vjk += n;
+         }
+      }
+   }
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/submat.cpp
===================================================================
RCS file: Shared/newmat/submat.cpp
diff -N Shared/newmat/submat.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/submat.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,340 @@
+//$$ submat.cpp                         submatrices
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,11); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/****************************** submatrices *********************************/
+
+GetSubMatrix BaseMatrix::SubMatrix(int first_row, int last_row, int first_col,
+   int last_col) const
+{
+   REPORT
+   Tracer tr("SubMatrix");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   int c = first_col - 1; int d = last_col - first_col + 1;
+   if (a<0 || b<0 || c<0 || d<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, a, b, c, d, false);
+}
+
+GetSubMatrix BaseMatrix::SymSubMatrix(int first_row, int last_row) const
+{
+   REPORT
+   Tracer tr("SubMatrix(symmetric)");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   if (a<0 || b<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix( this, a, b, a, b, true);
+}
+
+GetSubMatrix BaseMatrix::Row(int first_row) const
+{
+   REPORT
+   Tracer tr("SubMatrix(row)");
+   int a = first_row - 1;
+   if (a<0) Throw(SubMatrixDimensionException());
+   return GetSubMatrix(this, a, 1, 0, -1, false);
+}
+
+GetSubMatrix BaseMatrix::Rows(int first_row, int last_row) const
+{
+   REPORT
+   Tracer tr("SubMatrix(rows)");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   if (a<0 || b<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, a, b, 0, -1, false);
+}
+
+GetSubMatrix BaseMatrix::Column(int first_col) const
+{
+   REPORT
+   Tracer tr("SubMatrix(column)");
+   int c = first_col - 1;
+   if (c<0) Throw(SubMatrixDimensionException());
+   return GetSubMatrix(this, 0, -1, c, 1, false);
+}
+
+GetSubMatrix BaseMatrix::Columns(int first_col, int last_col) const
+{
+   REPORT
+   Tracer tr("SubMatrix(columns)");
+   int c = first_col - 1; int d = last_col - first_col + 1;
+   if (c<0 || d<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, 0, -1, c, d, false);
+}
+
+void GetSubMatrix::SetUpLHS()
+{
+   REPORT
+   Tracer tr("SubMatrix(LHS)");
+   const BaseMatrix* bm1 = bm;
+   GeneralMatrix* gm1 = ((BaseMatrix*&)bm)->Evaluate();
+   if ((BaseMatrix*)gm1!=bm1)
+      Throw(ProgramException("Invalid LHS"));
+   if (row_number < 0) row_number = gm1->Nrows();
+   if (col_number < 0) col_number = gm1->Ncols();
+   if (row_skip+row_number > gm1->Nrows()
+      || col_skip+col_number > gm1->Ncols())
+         Throw(SubMatrixDimensionException());
+}
+
+void GetSubMatrix::operator<<(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<)"); GeneralMatrix* gmx = 0;
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Copy(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      LoadAndStoreFlag lasf =
+         (  row_skip == col_skip
+            && gm->Type().IsSymmetric()
+            && gmx->Type().IsSymmetric() )
+        ? LoadOnEntry+DirectPart
+        : LoadOnEntry;
+      MatrixRow mrx(gmx, lasf);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.CopyCheck(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator<<(const Real* r)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<Real*)");
+   SetUpLHS();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+      Throw(SubMatrixDimensionException());
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::operator<<(const int* r)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<int*)");
+   SetUpLHS();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+      Throw(SubMatrixDimensionException());
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::operator=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(=Real)");
+   SetUpLHS();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::Inject(const GeneralMatrix& gmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(inject)");
+   SetUpLHS();
+   if (row_number != gmx.Nrows() || col_number != gmx.Ncols())
+      Throw(IncompatibleDimensionsException());
+   MatrixRow mrx((GeneralMatrix*)(&gmx), LoadOnEntry);
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Inject(mrx); mr.Next(); mrx.Next();
+   }
+}
+
+void GetSubMatrix::operator+=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(+=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check(mrx);                            // check for loss of info
+         sub.Add(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator-=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(-=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check(mrx);                            // check for loss of info
+         sub.Sub(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(+= or -= Real)");
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS();
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check();                               // check for loss of info
+         sub.Add(r); mr.Next();
+      }
+   }
+
+   CatchAll
+   {
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(*= or /= Real)");
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS();
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Multiply(r); mr.Next();
+      }
+   }
+
+   CatchAll
+   {
+      ReThrow;
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/svd.cpp
===================================================================
RCS file: Shared/newmat/svd.cpp
diff -N Shared/newmat/svd.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/svd.cpp	16 Jun 2004 21:16:41 -0000	1.1
@@ -0,0 +1,204 @@
+//$$svd.cpp                           singular value decomposition
+
+// Copyright (C) 1991,2,3,4,5: R B Davies
+// Updated 17 July, 1995
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "newmatrm.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,15); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+
+
+void SVD(const Matrix& A, DiagonalMatrix& Q, Matrix& U, Matrix& V,
+   bool withU, bool withV)
+// from Wilkinson and Reinsch: "Handbook of Automatic Computation"
+{
+   REPORT
+   Tracer trace("SVD");
+   Real eps = FloatingPointPrecision::Epsilon();
+   Real tol = FloatingPointPrecision::Minimum()/eps;
+
+   int m = A.Nrows(); int n = A.Ncols();
+   if (m<n)
+      Throw(ProgramException("Want no. Rows >= no. Cols", A));
+   if (withV && &U == &V)
+      Throw(ProgramException("Need different matrices for U and V", U, V));
+   U = A; Real g = 0.0; Real f,h; Real x = 0.0; int i;
+   RowVector E(n); RectMatrixRow EI(E,0); Q.ReSize(n);
+   RectMatrixCol UCI(U,0); RectMatrixRow URI(U,0,1,n-1);
+
+   if (n) for (i=0;;)
+   {
+      EI.First() = g; Real ei = g; EI.Right(); Real s = UCI.SumSquare();
+      if (s<tol) { REPORT Q.element(i) = 0.0; }
+      else
+      {
+         REPORT
+         f = UCI.First(); g = -sign(sqrt(s), f); h = f*g-s; UCI.First() = f-g;
+         Q.element(i) = g; RectMatrixCol UCJ = UCI; int j=n-i;
+         while (--j) { UCJ.Right(); UCJ.AddScaled(UCI, (UCI*UCJ)/h); }
+      }
+
+      s = URI.SumSquare();
+      if (s<tol) { REPORT g = 0.0; }
+      else
+      {
+         REPORT
+         f = URI.First(); g = -sign(sqrt(s), f); URI.First() = f-g;
+         EI.Divide(URI,f*g-s); RectMatrixRow URJ = URI; int j=m-i;
+         while (--j) { URJ.Down(); URJ.AddScaled(EI, URI*URJ); }
+      }
+
+      Real y = fabs(Q.element(i)) + fabs(ei); if (x<y) { REPORT x = y; }
+      if (++i == n) { REPORT break; }
+      UCI.DownDiag(); URI.DownDiag();
+   }
+
+   if (withV)
+   {
+      REPORT
+      V.ReSize(n,n); V = 0.0; RectMatrixCol VCI(V,n-1,n-1,1);
+      if (n) { VCI.First() = 1.0; g=E.element(n-1); if (n!=1) URI.UpDiag(); }
+      for (i=n-2; i>=0; i--)
+      {
+         VCI.Left();
+         if (g!=0.0)
+         {
+            VCI.Divide(URI, URI.First()*g); int j = n-i;
+            RectMatrixCol VCJ = VCI;
+            while (--j) { VCJ.Right(); VCJ.AddScaled( VCI, (URI*VCJ) ); }
+         }
+         VCI.Zero(); VCI.Up(); VCI.First() = 1.0; g=E.element(i);
+         if (i==0) break;
+         URI.UpDiag();
+      }
+   }
+
+   if (withU)
+   {
+      REPORT
+      for (i=n-1; i>=0; i--)
+      {
+         g = Q.element(i); URI.Reset(U,i,i+1,n-i-1); URI.Zero();
+         if (g!=0.0)
+         {
+            h=UCI.First()*g; int j=n-i; RectMatrixCol UCJ = UCI;
+            while (--j)
+            {
+               UCJ.Right(); UCI.Down(); UCJ.Down(); Real s = UCI*UCJ;
+               UCI.Up(); UCJ.Up(); UCJ.AddScaled(UCI,s/h);
+            }
+            UCI.Divide(g);
+         }
+         else UCI.Zero();
+         UCI.First() += 1.0;
+         if (i==0) break;
+         UCI.UpDiag();
+      }
+   }
+
+   eps *= x;
+   for (int k=n-1; k>=0; k--)
+   {
+      Real z = -FloatingPointPrecision::Maximum(); // to keep Gnu happy
+      Real y; int limit = 50; int l = 0;
+      while (limit--)
+      {
+         Real c, s; int i; int l1=k; bool tfc=false;
+         for (l=k; l>=0; l--)
+         {
+//          if (fabs(E.element(l))<=eps) goto test_f_convergence;
+            if (fabs(E.element(l))<=eps) { REPORT tfc=true; break; }
+            if (fabs(Q.element(l-1))<=eps) { REPORT l1=l; break; }
+            REPORT
+         }
+         if (!tfc)
+         {
+            REPORT
+            l=l1; l1=l-1; s = -1.0; c = 0.0;
+            for (i=l; i<=k; i++)
+            {
+               f = - s * E.element(i); E.element(i) *= c;
+//             if (fabs(f)<=eps) goto test_f_convergence;
+               if (fabs(f)<=eps) { REPORT break; }
+               g = Q.element(i); h = pythag(g,f,c,s); Q.element(i) = h;
+               if (withU)
+               {
+                  REPORT
+                  RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,l1);
+                  ComplexScale(UCJ, UCI, c, s);
+               }
+            }
+         }
+//       test_f_convergence: z = Q.element(k); if (l==k) goto convergence;
+         z = Q.element(k);  if (l==k) { REPORT break; }
+
+         x = Q.element(l); y = Q.element(k-1);
+         g = E.element(k-1); h = E.element(k);
+         f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y);
+         if (f>1)         { REPORT g = f * sqrt(1 + square(1/f)); }
+         else if (f<-1)   { REPORT g = -f * sqrt(1 + square(1/f)); }
+         else             { REPORT g = sqrt(f*f + 1); }
+            { REPORT f = ((x-z)*(x+z) + h*(y / ((f<0.0) ? f-g : f+g)-h)) / x; }
+
+         c = 1.0; s = 1.0;
+         for (i=l+1; i<=k; i++)
+         {
+            g = E.element(i); y = Q.element(i); h = s*g; g *= c;
+            z = pythag(f,h,c,s); E.element(i-1) = z;
+            f = x*c + g*s; g = -x*s + g*c; h = y*s; y *= c;
+            if (withV)
+            {
+               REPORT
+               RectMatrixCol VCI(V,i); RectMatrixCol VCJ(V,i-1);
+               ComplexScale(VCI, VCJ, c, s);
+            }
+            z = pythag(f,h,c,s); Q.element(i-1) = z;
+            f = c*g + s*y; x = -s*g + c*y;
+            if (withU)
+            {
+               REPORT
+               RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,i-1);
+               ComplexScale(UCI, UCJ, c, s);
+            }
+         }
+         E.element(l) = 0.0; E.element(k) = f; Q.element(k) = x;
+      }
+      if (l!=k) { Throw(ConvergenceException(A)); }
+// convergence:
+      if (z < 0.0)
+      {
+         REPORT
+         Q.element(k) = -z;
+         if (withV) { RectMatrixCol VCI(V,k); VCI.Negate(); }
+      }
+   }
+   if (withU & withV) SortSV(Q, U, V);
+   else if (withU) SortSV(Q, U);
+   else if (withV) SortSV(Q, V);
+   else SortDescending(Q);
+}
+
+void SVD(const Matrix& A, DiagonalMatrix& D)
+{ REPORT Matrix U; SVD(A, D, U, U, false, false); }
+
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/docs/nm11.htm
===================================================================
RCS file: Shared/newmat/docs/nm11.htm
diff -N Shared/newmat/docs/nm11.htm
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/docs/nm11.htm	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,3794 @@
+<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
+ 
+<HTML>
+ 
+<HEAD>
+<meta http-equiv="Content-Language" content="en-nz">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+
+<TITLE>Newmat11 documentation</TITLE>
+<link rel="stylesheet" type="text/css" href="rbd.css">
+<link REL="SHORTCUT ICON" HREF="favicon.ico">
+</HEAD>
+
+<BODY>
+<H1><A NAME="top"></A>Documentation for newmat11, a matrix library in C++</H1>
+<P CLASS="small"><A HREF="#intro">next</A> - <A HREF="#top">skip</A> -
+<A HREF="ol_doc.htm">up</A> - <A HREF="#top">start</A><BR>
+<A HREF="ol_doc.htm">return to online documentation page</A></P>
+<P><B>Copyright (C)  2004: R B Davies</B></P>
+<P><i>28 March, 2004</i> - beta version.</P>
+<TABLE WIDTH=100%>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#intro">1.
+Introduction</A><BR>
+<A HREF="#starting">2. Getting started</A><BR>
+<A HREF="#refer">3. Reference manual</A></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#error">4.
+Error messages</A><BR>
+<A HREF="#design">5. Design of the library</A></TD>
+</TR>
+</TABLE>
+<P>This is the <I>how to use</I> documentation for <I>newmat</I> plus some
+background information on its design. </P>
+<P>There is additional support material on my <A HREF="#where">web site</A>. 
+</P>
+<P CLASS="small">Navigation:&nbsp; This page is arranged in sections,
+sub-sections and sub-sub-sections; four cross-references are given at the top
+of these. <I>Next</I> takes you through the sections, sub-sections and
+sub-sub-sections in order. <I>Skip</I> goes to the next section, sub-section or
+sub-sub-section at the same level in the hierarchy as the section, sub-section
+or sub-sub-section that you are currently reading. <I>Up</I> takes you up one
+level in the hierarchy and <I>start</I> gets you back here.</P>
+<P><B>Please read the sections on <A HREF="#custom">customising</A> and
+<a href="#compiler">compilers</a> before
+attempting to compile <i>newmat</i>.</B> </P>
+<H2><A NAME="intro"></A>1. Introduction</H2>
+<P CLASS="small"><A HREF="#use">next</A> - <A HREF="#starting">skip</A> -
+<A HREF="#top">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH=100%>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#use">1.1
+Conditions of use</A><BR>
+<A HREF="#descript">1.2 Description</A><BR>
+<A HREF="#which">1.3 Is this the library for you?</A><BR>
+<A HREF="#other">1.4 Other matrix libraries</A></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#where">1.5
+Where to find this library</A><BR>
+<A HREF="#author">1.6 How to contact the author</A><BR>
+<A HREF="#changes">1.7 Change history</A><BR>
+<A HREF="#sources">1.8 References</A></TD>
+</TR>
+</TABLE>
+<H2><A NAME="use"></A>1.1 Conditions of use</H2>
+<P CLASS="small"><A HREF="#descript">next</A> - <A HREF="#descript">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<P>There are no restrictions on the use of <I>newmat</I> except that I take no
+liability for any problems that may arise from this use.</P>
+<P>I welcome its distribution as part of low cost CD-ROM collections. </P>
+<P>You can use it in your commercial projects. However, if you distribute the
+source, please make it clear which parts are mine and that they are available
+essentially for free over the Internet. </P>
+<HR>
+<P><STRONG>Please understand that there may still be bugs and errors. Use at
+your own risk. I take no responsibility for any errors or omissions in this
+package or for any misfortune that may befall you or others as a result of its
+use.</STRONG> </P>
+<HR>
+<P>Please report bugs to me at <B>robert (at) statsresearch.co.nz</B>&nbsp;&nbsp; 
+[replace (at) by you-know-what-character in the email address].</P>
+<P>When reporting a bug please tell me which C++ compiler you are using, and
+what version. Also give me details of your computer. And tell me which version
+of <I>newmat</I> (e.g. newmat03 or newmat04) you are using. Note any changes
+you have made to my code. If at all possible give me a piece of code
+illustrating the bug. See the <A HREF="#problem">problem report form</A>. </P>
+<P><I>Please do report bugs to me.</I> </P>
+<H2><A NAME="descript"></A>1.2 General description
+</H2>
+<P CLASS="small"><A HREF="#which">next</A> - <A HREF="#which">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<P>The package is intended for scientists and engineers who need to manipulate
+a variety of types of matrices using standard matrix operations. Emphasis is on
+the kind of operations needed in statistical calculations such as least
+squares, linear equation solve and eigenvalues. </P>
+<P>It supports matrix types </P>
+<BLOCKQUOTE>
+  <TABLE WIDTH="80%" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" cellpadding="0">
+<TR>
+<TD>Matrix</TD>
+<TD>rectangular matrix</TD>
+</TR>
+<TR>
+<TD>SquareMatrix</TD>
+<TD>square matrix</TD>
+</TR>
+<TR>
+<TD>nricMatrix</TD>
+<TD>for use with <I>Numerical Recipes in C</I> programs</TD>
+</TR>
+<TR>
+<TD>UpperTriangularMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>LowerTriangularMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>DiagonalMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>SymmetricMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>BandMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>UpperBandMatrix</TD>
+<TD>upper triangular band matrix</TD>
+</TR>
+<TR>
+<TD>LowerBandMatrix</TD>
+<TD>lower triangular band matrix</TD>
+</TR>
+<TR>
+<TD>SymmetricBandMatrix</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>RowVector</TD>
+<TD>derived from Matrix</TD>
+</TR>
+<TR>
+<TD>ColumnVector</TD>
+<TD>derived from Matrix</TD>
+</TR>
+<TR>
+<TD>IdentityMatrix</TD>
+<TD>diagonal matrix, elements have same value</TD>
+</TR>
+</TABLE>
+</BLOCKQUOTE>
+<P>Only one element type (float or double) is supported. </P>
+<P>The package includes the operations <TT>*</TT>, <TT>+</TT>, <TT>-</TT>,
+Kronecker product, Schur product, concatenation, inverse, transpose, conversion between types, submatrix,
+determinant, Cholesky decomposition, QR decomposition, singular value
+decomposition, eigenvalues of a symmetric matrix, sorting, fast Fourier
+transform, printing and an interface with <I>Numerical Recipes in C</I>. </P>
+<P>It is intended for matrices in the range 10 x 10 to the maximum size your
+machine will accommodate in a single array. The number of elements in an array
+cannot exceed the maximum size of an <I>int</I>. The package will work for very
+small matrices but becomes rather inefficient. Some of the factorisation
+functions are not (yet) optimised for paged memory and so become inefficient
+when used with very large matrices. </P>
+<P>A <I>lazy evaluation</I> approach to evaluating matrix expressions is used
+to improve efficiency and reduce the use of temporary storage. </P>
+<P>I have tested versions of the package on variety of compilers and platforms
+including  Borland, Gnu, Microsoft and Sun. For more details
+see the section on <A HREF="#compiler">compilers</A>. </P>
+<H2><A NAME="which"></A>1.3 Is this the library for
+you?</H2>
+<P CLASS="small"><A HREF="#other">next</A> - <A HREF="#other">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<P>Do you</P>
+<UL>
+<LI>understand <TT>*</TT> to mean matrix multiply and not element by element
+multiply </LI>
+<LI>need matrix operators such as <TT>*</TT> and <TT>+</TT> defined as
+operators so you can write things like <TT> X = A * (B + C);</TT></LI>
+<LI>need a variety of types of matrices (but not sparse)</LI>
+<LI>need only one element type (float or double)</LI>
+<LI>work with matrices in the range 10 x 10 up to what can be stored in memory 
+</LI>
+<LI>tolerate a moderately large but not huge package</LI>
+<LI>need high quality but not necessarily the latest numerical methods. </LI>
+</UL>
+<P>Then <I>newmat</I> may be the right matrix library for you. </P>
+<H2><A NAME="other"></A>1.4 Other matrix libraries
+</H2>
+<P CLASS="small"><A HREF="#where">next</A> - <A HREF="#where">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<P>For details of other C++ matrix libraries look at
+<a href="http://www.robertnz.net/cpp_site.html">http://www.robertnz.net/cpp_site.html</a>.
+Look at the section <I>lists of libraries</I> which gives the locations of
+several very comprehensive lists of matrix and other C++ libraries and at the
+section <I>source code</I>. Or just search on Google.</P>
+<H2><A NAME="where"></A>1.5 Where to find this
+library</H2>
+<P CLASS="small"><A HREF="#author">next</A> - <A HREF="#author">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A> </P>
+<UL>
+<LI><a href="http://www.robertnz.net">http://www.robertnz.net</a></LI>
+</UL>
+<H2><A NAME="author"></A>1.6 How to contact the
+author</H2>
+<P CLASS="small"><A HREF="#changes">next</A> - <A HREF="#changes">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<PRE>   Robert Davies
+   16 Gloucester Street
+   Wilton
+   Wellington
+   New Zealand
+
+   <I>Internet:</I> robert<b>(at)</b>statsresearch.co.nz</PRE>
+
+[replace (at) by you-know-what.]
+
+
+<H2><A NAME="changes"></A>1.7 Change history</H2>
+<P CLASS="small"><A HREF="#sources">next</A> - <A HREF="#sources">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<P><b>Newmat11 - March, 2004:</b></P>
+<P CLASS="small">Remove work-arounds for older compilers, Borland Builder 6 compatibility, SquareMatrix, 
+load from array of ints, CrossProducts, Cholesky and QRZ update functions, swap 
+functions, FFT2, access to arrays in traditional C functions, SimpleIntArray 
+class, compatibility with Numerical Recipes in C++, speed-ups and bug-fixes.</P>
+<P><b>Newmat10A - October, 2002:</b></P>
+<P CLASS="small">Fix error in Kronecker product; fixes for Intel and GCC3 
+compilers.</P>
+<P><B>Newmat10 - January, 2002:</B> </P>
+<P CLASS="small">Improve compatibility with GCC, fix errors in FFT and
+GenericMatrix, update simulated exceptions, maxima, minima, determinant, dot
+product and Frobenius norm functions, update make files for CC and GCC, faster
+FFT, <TT>A.ReSize(B)</TT>, fix pointer arithmetic, <TT>&lt;&lt;</TT> for loading 
+data into rows, IdentityMatrix, Kronecker product, sort singular values.</P>
+<P><B>Newmat09 - September, 1997:</B> </P>
+<P CLASS="small">Operator <TT>==</TT>, <TT>!=</TT>, <TT>+=</TT>, <TT>-=</TT>,
+<TT>*=</TT>, <TT>/=</TT>, <TT>|=</TT>, <TT>&amp;=</TT>. Follow new rules for
+<I>for (int i; ... )</I> construct. Change Boolean, TRUE, FALSE to bool, true,
+false. Change ReDimension to ReSize. SubMatrix allows zero rows and columns.
+Scalar <TT>+</TT>, <TT>-</TT> or <TT>*</TT> matrix is OK. Simplify simulated
+exceptions. Fix non-linear programs for AT&amp;T compilers. Dummy inequality
+operators. Improve internal row/column operations. Improve matrix LU
+decomposition. Improve sort. Reverse function. IsSingular function. Fast trig
+transforms. Namespace definitions. </P>
+<P><B>Newmat08A - July, 1995:</B> </P>
+<P CLASS="small">Fix error in SVD. </P>
+<P><B>Newmat08 - January, 1995:</B> </P>
+<P CLASS="small">Corrections to improve compatibility with Gnu, Watcom.
+Concatenation of matrices. Elementwise products. Option to use compilers
+supporting exceptions. Correction to exception module to allow global
+declarations of matrices. Fix problem with inverse of symmetric matrices. Fix
+divide-by-zero problem in SVD. Include new QR routines. Sum function.
+Non-linear optimisation. GenericMatrices. </P>
+<P><B>Newmat07 - January, 1993</B> </P>
+<P CLASS="small">Minor corrections to improve compatibility with Zortech,
+Microsoft and Gnu. Correction to exception module. Additional FFT functions.
+Some minor increases in efficiency. Submatrices can now be used on RHS of =.
+Option for allowing C type subscripts. Method for loading short lists of
+numbers. </P>
+<P><B>Newmat06 - December 1992:</B> </P>
+<P CLASS="small">Added band matrices; 'real' changed to 'Real' (to avoid
+potential conflict in complex class); Inject doesn't check for no loss of
+information; fixes for AT&amp;T C++ version 3.0; real(A) becomes A.AsScalar();
+CopyToMatrix becomes AsMatrix, etc; .c() is no longer required (to be deleted
+in next version); option for version 2.1 or later. Suffix for include files
+changed to .h; BOOL changed to Boolean (BOOL doesn't work in g++ v 2.0);
+modifications to allow for compilers that destroy temporaries very quickly;
+(Gnu users - see the section of compilers). Added CleanUp,
+LinearEquationSolver, primitive version of exceptions. </P>
+<P><B>Newmat05 - June 1992:</B> </P>
+<P CLASS="small">For private release only </P>
+<P><B>Newmat04 - December 1991:</B> </P>
+<P CLASS="small">Fix problem with G++1.40, some extra documentation  
+</P>
+<P><B>Newmat03 - November 1991:</B> </P>
+<P CLASS="small">Col and Cols become Column and Columns. Added Sort, SVD,
+Jacobi, Eigenvalues, FFT, real conversion of 1x1 matrix, <I>Numerical Recipes
+in C</I> interface, output operations, various scalar functions. Improved
+return from functions. Reorganised setting options in &quot;include.hxx&quot;.
+</P>
+<P><B>Newmat02 - July 1991:</B> </P>
+<P CLASS="small">Version with matrix row/column operations and numerous
+additional functions. </P>
+<P><B>Matrix - October 1990:</B> </P>
+<P CLASS="small">Early version of package. </P>
+<H2><A NAME="sources"></A>1.8 References</H2>
+<P CLASS="small"><A HREF="#starting">next</A> - <A HREF="#starting">skip</A> -
+<A HREF="#intro">up</A> - <A HREF="#top">start</A></P>
+<UL>
+<LI>The matrix LU decomposition is from Golub, G.H. &amp; Van Loan, C.F.
+(1996), <I>Matrix Computations</I>, published by Johns Hopkins University
+Press. </LI>
+<LI>Part of the matrix inverse/solve routine is adapted from Press, Flannery,
+Teukolsky, Vetterling (1988), <I>Numerical Recipes in C</I>, published by the
+Cambridge University Press. </LI>
+<LI>Many of the advanced matrix routines are adapted from routines in Wilkinson
+and Reinsch (1971), <I>Handbook for Automatic Computation, Vol II, Linear
+Algebra</I> published by Springer Verlag. </LI>
+<LI>The fast Fourier transform is adapted from Carl de Boor (1980), <I>Siam J
+Sci Stat Comput</I>, pp173-8 and the fast trigonometric transforms from Charles
+Van Loan (1992) in <I>Computational frameworks for the fast Fourier
+transform</I> published by SIAM. </LI>
+<LI>The sort function is derived from Sedgewick, Robert (1992), <I>Algorithms
+in C++</I> published by Addison Wesley. </LI>
+</UL>
+<P>For references about <I>Newmat</I> see </P>
+<UL>
+<LI>Davies, R.B. (1994) Writing a matrix package in C++. In OON-SKI'94: The
+second annual object-oriented numerics conference, pp 207-213. Rogue Wave
+Software, Corvallis. </LI>
+<LI>Eddelbuttel, Dirk (1996) Object-oriented econometrics: matrix programming
+in C++ using GCC and Newmat. Journal of Applied Econometrics, Vol 11, No 2, pp
+199-209. </LI>
+</UL>
+<H2><A NAME="starting"></A>2. Getting started</H2>
+<P CLASS="small"><A HREF="#overview">next</A> - <A HREF="#refer">skip</A> -
+<A HREF="#top">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH="100%">
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A
+HREF="#overview">2.1 Overview</A><BR>
+<A HREF="#make">2.2 Make files</A><BR>
+<A HREF="#custom">2.3 Customising</A><BR>
+<A HREF="#compiler">2.4 Compilers</A><BR>
+<a HREF="#update">2.5 Updating from previous versions</a><br>
+<a HREF="#except_1">2.6 Catching exceptions</a></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A
+HREF="#example">2.7 Example</A><BR>
+<A HREF="#testing">2.8 Testing</A><BR>
+<A HREF="#bugs">2.9 Bugs</A><BR>
+<a href="#problemareas">2.10 Problem areas</a><BR>
+<A HREF="#files">2.11 Files in newmat11</A><BR>
+<A HREF="#problem">2.12 Problem report form</A></TD>
+</TR>
+</TABLE>
+<H2><A NAME="overview"></A>2.1 Overview</H2>
+<P CLASS="small"><A HREF="#make">next</A> - <A HREF="#make">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>I use .h as the suffix of definition files and .cpp as the suffix of C++
+source files. </P>
+<P>You will need to compile all the *.cpp files listed as program files in the
+<A HREF="#files">files section</A> to get the complete package. Ideally you
+should store the resulting object files as a library. The tmt*.cpp files are
+used for <A HREF="#testing">testing</A>, example.cpp is an <A
+HREF="#example">example</A> and sl_ex.cpp, nl_ex.cpp and garch.cpp are examples
+of the <A HREF="#nonlin">non-linear</A> solve and optimisation routines. A
+demonstration and test of the exception mechanism is in test_exc.cpp. </P>
+<P>I include a number of <I>make</I> files for compiling the example and the
+test package. See the section on <A HREF="#make">make files</A> for details.
+But with the PC compilers, its pretty quick just to load all the files in the
+interactive environments by pointing and clicking. </P>
+<P>Use the large or win32 console model when you are using a PC. Do not
+<I>outline</I> inline functions. You may need to increase the stack size. </P>
+<P>Your source files that access the newmat will need to #include one or more
+of the following files. </P>
+<TABLE WIDTH="100%" CELLPADDING="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
+<TR>
+<TD VALIGN="TOP">include.h</TD>
+<TD>to access just the compiler options</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP">newmat.h</TD>
+<TD>to access just the main matrix library (includes include.h)</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP">newmatap.h</TD>
+<TD>to access the advanced matrix routines such as Cholesky decomposition, QR
+triangularisation etc (includes newmat.h)</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP">newmatio.h</TD>
+<TD>to access the <A HREF="#output">output</A> routines (includes newmat.h) You
+can use this only with compilers that support the standard input/output
+routines including manipulators</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP">newmatnl.h</TD>
+<TD>to access the non-linear optimisation routines (includes newmat.h)</TD>
+</TR>
+</TABLE>
+<P>See the section on <A HREF="#custom">customising</A> to see how to edit
+include.h for your environment and the section on <A
+HREF="#compiler">compilers</A> for any special problems with the compiler you
+are using. </P>
+<H2><A NAME="make"></A>2.2 Make files</H2>
+<P CLASS="small"><A HREF="#custom">next</A> - <A HREF="#custom">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>I have included <I>make</I> files for CC, Borland 5.5, 5.6, Microsoft VC++6 and Gnu compilers. You 
+can generate make files for a number of other compilers with my
+<a href="genmake.htm">genmake</a> utility. Make files provide
+a way of compiling your programs  without using the IDE that comes with
+PC compilers. See the <A HREF="#files">files section</A> for details. See the
+<A HREF="#example">example</A> for how to use them. Leave out the target name
+to compile and link all my examples and test files. </P>
+<H3>PC</H3>
+<P>I include  make files for Borland 5.5, 5.6 and Microsoft VC++6 or 7. With the 
+Borland compiler you will need to edit it to show where 
+you have stored your Borland compiler. For make files for other compilers use my
+<a href="genmake.htm">genmake</a> utility. To compile my test and example 
+programs use Borland 5.5 (Builder 5) use</P>
+<pre>   make -f nm_b55.mak</pre>
+<p>or with Borland 5.6 (Builder 6) use</p>
+<pre>   make -f nm_b56.mak</pre>
+<P>or with Microsoft VC++ 6 or 7 use</P>
+<pre>   make -f nm_m6.mak</pre>
+<P>There are some more notes in the
+<a href="genmake.htm">genmake</a> documentation about using these make files.</P>
+<H3>Unix</H3>
+<P>The <I>make</I> file for the Unix CC compilers link a .cxx file to each .cpp
+file since some of these compilers do not recognise .cpp as a legitimate
+extension for a C++ file. I suggest you delete this part of the <I>make</I>
+file and, if necessary, rename the .cpp files to something your compiler
+recognises. </P>
+<P>My <I>make</I> file for Gnu GCC on Unix systems is for use with
+<TT>gmake</TT> rather than <TT>make</TT>. I assume your compiler recognises the
+.cpp extension. Ordinary <TT>make</TT> works with it on the Sun but not the
+Silicon Graphics or HP machines. On Linux use <TT>make</TT>. </P>
+<P>My make file for the CC compilers works with the ordinary make. </P>
+<P>To compile everything with the CC compiler use </P>
+<PRE>   make -f nm_cc.mak
+</PRE>
+
+<P>or for the gnu compiler use </P>
+<PRE>   make -f nm_gnu.mak
+</PRE>
+
+<P>On some computers you will need to use <tt>gmake</tt> rather than <tt>make</tt>.</P>
+
+<P>There is a line in the make file for CC <TT>rm -f $*.cxx</TT>. Some systems
+won't accept this line and you will need to delete it. In this case, if you
+have a bad compile and you are using my scheme for linking .cxx files, you will
+need to delete the .cxx file link generated by that compile before you can do
+the next one. </P>
+<H2><A NAME="custom"></A>2.3 Customising</H2>
+<P CLASS="small"><A HREF="#compiler">next</A> - <A HREF="#compiler">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>The file <I>include.h</I> sets a variety of options including several
+compiler dependent options. You may need to edit include.h to get the options
+you require. If you are using a compiler different from one I have worked with
+you may have to set up a new section in include.h appropriate for your
+compiler. </P>
+<P>Borland, Turbo, Gnu, Microsoft and Watcom are recognised automatically. If
+none of these are recognised a default set of options is used. These are fine
+for AT&amp;T, HPUX and Sun C++. If you using a compiler I don't know about you
+may have to write a new set of options. </P>
+<P>There is an option in include.h for selecting whether you use compiler
+supported exceptions, simulated exceptions, or disable exceptions. I now set
+<I> compiler supported exceptions</I> as the default. Use the option for
+compiler supported exceptions <I>if and only if</I> you have set the option on
+your compiler to recognise exceptions. Disabling exceptions sometimes helps
+with compilers that are incompatible with my exception simulation scheme. </P>
+<P>Activate the appropriate statement to make the element type float or double.
+</P>
+<P>The option <A HREF="#testing">DO_FREE_CHECK</A> is used for tracking memory
+leaks and normally should not be activated. </P>
+<P>Activate SETUP_C_SUBSCRIPTS if you want to use traditional C style
+<A HREF="#elements">element access</A>. Note that this does <I>not</I> change
+the starting point for indices when you are using round brackets for accessing
+elements or selecting submatrices. It does enable you to use C style square
+brackets. This also activates additional constructors for Matrix, ColumnVector 
+and RowVector to simplify use with <i>Numerical Recipes in C++</i>.</P>
+<P>Activate <TT>#define use_namespace</TT> if you want to use <A
+HREF="#namesp">namespaces</A>. Do this only if you are sure your compiler
+supports namespaces. If you do turn this option on, be prepared to turn it off
+again if the compiler reports inaccessible variables or the linker reports
+missing links. </P>
+<P>Activate <TT>#define _STANDARD_</TT> to use the standard names for the
+included files and to find the floating point precision data using the floating
+point standard. This will work only with the most recent compilers. </P>
+<P>If you haven't defined <TT>_STANDARD_</TT> and are using a compiler that
+<I>include.h</I> does not recognise and you want to pick up the floating point
+precision data from <I>float.h</I> then activate <TT>#define use_float_h</TT>.
+Otherwise the floating point precision data will be accessed from
+<I>values.h</I>. You may need to do this with computers from Digital, in
+particular. </P>
+<H2><A NAME="compiler"></A>2.4 Compilers</H2>
+<P CLASS="small"><A HREF="#atandt">next</A> - <A HREF="#update">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH="100%">
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%">
+<A HREF="#atandt">2.4.1 AT&amp;T </A><BR>
+<A HREF="#borland">2.4.2 Borland </A><BR>
+<A HREF="#gcc">2.4.3 Gnu G++ </A><BR>
+<A HREF="#hpux">2.4.4 HPUX </A> </TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%">
+<A HREF="#intel">2.4.5 Intel </A><BR>
+<A HREF="#microso">2.4.6 Microsoft </A><BR>
+<A HREF="#sun">2.4.7 Sun </A><BR>
+<A HREF="#watcom">2.4.8 Watcom </A></TD>
+</TR>
+</TABLE>
+<P>I have tested this library on a number of compilers. Here are the levels of
+success and any special considerations. In most cases I have chosen code that
+works under all the compilers I have access to, but I have had to include some
+specific work-arounds for some compilers. For the newest PC versions,  I use a Pentium 
+4 computer running windows XP or Linux
+(Red Hat 9.0). The older compilers are tested on older computers. The Unix versions are on a Sun Sparc
+station. Thanks to Victoria University for access to the Sparc. </P>
+<P>I have set up a block of code for each of the compilers in include.h. Turbo,
+Borland, Gnu, Microsoft and Watcom are recognised automatically. There is a
+default option that works for AT&amp;T, Sun C++ and HPUX. So you don't
+have to make any changes for these compilers. Otherwise you may have to build
+your own set of options in include.h. </P>
+<H2><A NAME="atandt"></A>2.4.1 AT&amp;T</H2>
+<P CLASS="small"><A HREF="#borland">next</A> - <A HREF="#borland">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<P>The AT&amp;T compiler used to be available on a wide variety of Unix
+workstations. I don't know if anyone still uses it. However the AT&amp;T options are 
+the default if your compiler is not recognised.</P>
+<P>AT&amp;T C++ 2.1; 3.0.1 on a Sun: Previous versions worked on these
+compilers, which I no longer have access to. </P>
+<P>In AT&amp;T 2.1 you may get an error when you use an expression for the
+single argument when constructing a Vector or DiagonalMatrix or one of the
+Triangular Matrices. You need to evaluate the expression separately. </P>
+<H2><A NAME="borland"></A>2.4.2 Borland</H2>
+<P CLASS="small"><A HREF="#gcc">next</A> - <A HREF="#gcc">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<H3>Newer compilers</H3>
+<P><b>Borland Builder version 6:</b> My tests have been on the <i>personal</i> 
+version. See the notes for version 5. If you are 
+compiling with a make file you can use <i>nm_b56.mak</i> as a model. You can set 
+the <i>newmat</i> options to use namespace and the standard library. If you are 
+compiling a GUI program you may need to comment out the line defining <i>
+TypeDefException</i> in <i>include.h. </i>I don't believe exceptions work 
+completely correctly in either version 5 or version 6. However, this does not 
+seem to be a problem with my use of them in <i>newmat</i>.</P>
+<P><B>Borland Builder version 5:</B> This works fine in console mode and no
+special editing of the source codes is required. I haven't tested it in GUI
+mode. You can set the <i>newmat</i> options to use namespace and the standard library. <b> You
+should turn <I>off</I> the Borland option to use pre-compiled headers.</b> There 
+are notes on compiling with the IDE on my <a href="#where">website</a>. 
+Alternatively you can use the <i>nm_b55.mak</i> make file<i>.</i></P>
+<P><B>Borland Builder version 4</B>: I have successfully used this on older 
+versions of newmat using the
+console wizard (menu item file/new - select new tab). Use compiler
+exceptions. Suppose you are compiling my test program <I>tmt</I>. Rename my
+<I>main()</I> function in <I>tmt.cpp</I> to <I>my_main()</I>. Rename
+<I>tmt.cpp</I> to <I>tmt_main.cpp</I>. Borland will generate a new file
+<I>tmt.cpp</I> containing their <I>main()</I> function. Put the line <TT>int
+my_main();</TT> above this function and put <TT>return my_main();</TT> into the
+body of <I>main()</I>.</P>
+<P><B>Borland compiler version 5.5</B>: this is the free C++ compiler available
+from Borland's web site. I suggest you use
+the compiler supported exceptions and turn on <I>standard</I> in include.h. You
+can use the make file <i>nm_b55.mak</i> after editing to correct the file locations for
+your system.</P>
+<H3>Older compilers</H3>
+<P><B>Borland C++  5.02</B>: Use the large or 32 bit flat model. If you are not debugging, turn off the 
+options that collect debugging information. Use my simulated exceptions.</P>
+<P>When running my test program under ms-dos you may run out of memory. Either
+compile the test routine to run under <I>easywin</I> or use simulated exceptions 
+rather than the built in exceptions. </P>
+<P>If you can, upgrade to windows 95 or window NT and use the 32 bit console
+model. </P>
+<P>If you are using the 16 bit large model, don't forget to keep all matrices
+less than 64K bytes in length (90x90 for a rectangular matrix if you are using
+<TT>double</TT> as your element type). Otherwise your program will crash
+without warning or explanation. You will need to break the <A
+HREF="#testing">tmt</A> set of test files into several parts to get the program 
+to fit into your computer and run without stack overflow. </P>
+<P>One version of Borland had DBL_MIN incorrectly defined. If you are using an
+older version of Borland and are getting strange numerical errors in the test
+programs reinstate the commented out statements in precision.h. </P>
+<P>You can generate make files for versions 5  with my <a href="genmake.htm">
+genmake</a> utility.</P>
+<P><b>Borland C++ 3 and 4</b>.</P>
+<P>This version of Newmat is not compatible with these compilers.</P>
+<H2><A NAME="gcc"></A>2.4.3 Gnu G++</H2>
+<P CLASS="small"><A HREF="#hpux">next</A> - <A HREF="#hpux">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<P><B>Gnu G++ 2.95, 2.96, 3.1:</B> This works OK. If you are using a much earlier version
+see if you can upgrade. You can't use standard with the 2.9X 
+versions. The namespace option worked with 2.96 on Linux but not iwth 2.95 on 
+the Sun. Standard is automatically turned on with the 3.X.</P>
+<P>This version of Newmat is not compatible with versions 2.6 or earlier.</P>
+<H2><A NAME="hpux"></A>2.4.4 HP-UX</H2>
+<P CLASS="small"><A HREF="#intel">next</A> - <A HREF="#intel">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<P>HP 9000 series HP-UX. I no longer have access to this compiler. Newmat09
+worked without problems with the simulated exceptions; haven't tried the
+built-in exceptions. </P>
+<P>With recent versions of the compiler you may get warning messages like
+<TT>Unsafe cast between pointers/references to incomplete classes</TT>. At
+present, I think these can be ignored. </P>
+
+<h2><a name="intel"></a>2.4.5 Intel</h2>
+<P CLASS="small"><A HREF="#microso">next</A> - <A HREF="#microso">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+
+<P>Newmat works correctly with the Intel versions 5 and 8 C++ compiler for Windows and for 
+versions 5 and 8 for Linux. (Not tested for the other versions). Standard is 
+automatically turned on for the Linux versions. Note that the Intel compiler for 
+Linux is free for non-commercial use.</P>
+
+<H2><A NAME="microso"></A>2.4.6 Microsoft</H2>
+<P CLASS="small"><A HREF="#sun">next</A> - <A HREF="#sun">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<H3>Newer versions</H3>
+<P>See my <A HREF="#where">web site</A> for instructions how to work
+Microsoft's IDE.<B></B></P>
+<P><b>Microsoft Visual C++ 7:</b> This works OK. Note that all my tests have 
+been in console mode. You can turn on my standard and namespace options.</P>
+<P><B>Microsoft Visual C++ 6</B>: <b>Get the latest service pack</b>. I have tried this 
+in console mode and it seems to work satisfactorily. Use the compiler supported exceptions. You may be able to
+use the namespace and standard options. If you want to work under MFC
+you may need to <TT>#include &quot;stdafx.h&quot;</TT> at the beginning of each .cpp file 
+(if you want precompiled headers). </P>
+<P><B>Microsoft Visual C++ 5</B>: I have tried this in console mode and it
+seems to work satisfactorily. There may be a problem with <A
+HREF="#namesp">namespace</A> (fixed by Service Pack 3?). <B>Turn optimisation
+off</B>. Use the compiler supported exceptions. If
+you want to work under MFC&nbsp;
+you may need to <TT>#include &quot;stdafx.h&quot;</TT> at the
+beginning of each .cpp file (if you want precompiled headers).</P>
+<H3>Older versions</H3>
+<p>I doubt whether these will work.</p>
+<H2><A NAME="sun"></A>2.4.7 Sun</H2>
+<P CLASS="small"><A HREF="#watcom">next</A> - <A HREF="#watcom">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<P><B>Sun C++ (version 7):</B> This seems to work fine with 
+compiler supported exceptions. <B>Sun C++ (version
+5):</B> There was a problem with exceptions. If you use my simulated
+exceptions the non-linear optimisation programs hang. If you use the compiler
+supported exceptions my tmt and test_exc programs crash. You should
+<I>disable</I> exceptions.</P>
+<H2><A NAME="watcom"></A>2.4.8 Watcom</H2>
+<P CLASS="small"><A HREF="#update">next</A> - <A HREF="#update">skip</A> -
+<A HREF="#compiler">up</A> - <A HREF="#top">start</A></P>
+<P><B>Watcom C++ (version 10a):</B> this won't work as I no longer include the 
+simulated Booleans. I haven't tried more recent versions of Watcom. (I can <i>
+compile</i> with the downloadable version of Watcom 11c but haven't found out 
+how to <i>link</i> the files).</P>
+<H2><A NAME="update"></A>2.5 Updating from previous
+versions</H2>
+<P CLASS="small"><a href="#except_1">next</a> - <a href="#except_1">skip</a> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P><b>Newmat11 </b>- if you are upgrading from earlier versions note the 
+following:</P>
+<ul>
+  <li>The class <i>Exception</i> in <i>MyExcept.h</i> has been replaced by <i>
+  BaseException</i> and a <b>typedef</b> statement included so programs that use 
+  the <i>Exception</i> class will still work. If the <i>Exception</i> class was 
+  causing a problem comment out the line defining <i>TypeDefException</i> in <i>
+  include.h</i>.</li>
+  <li>Newmat11 does not support the TEMP_DESTROYED_QUICKLY options so won't 
+work with very old versions of Gnu G++.</li>
+  <li>Old AT&amp;T work-arounds are removed.</li>
+  <li>Newmat11 does not include the simulated Booleans so won't work with compilers that 
+don't support <b>bool</b>.</li>
+  <li>QRZ and QRZT no longer throw an exception if they generate a singular 
+  triangular matrix.</li>
+  <li>I am beginning a process of converting functions to lower case. Currently 
+  both the old and new names will work.</li>
+</ul>
+<P><B>Newmat10</B> includes new <A HREF="#scalar2">maxima, minima</A>,
+<A HREF="#scalar3">determinant, dot product and Frobenius norm</A> functions, a
+faster <A HREF="#fft">FFT</A>, revised <A HREF="#make">make</A> files for GCC
+and CC compilers, several corrections, new <A HREF="#dimen">ReSize</A> function, <a href="#constr">IdentityMatrix</a> 
+and <a href="#binary">Kronecker Product</a>. Singular values from <a href="#svd">
+SVD</a> are sorted. The program files include a new file, <TT>newfft.cpp</TT>, so you
+will need to include this in the list of files in your IDE and make files. There 
+is also a new test file tmtm.cpp.
+<A HREF="#pointer">Pointer arithmetic</A> now mostly meets requirements of
+standard. You can use <A HREF="#entering">&lt;&lt;</A> to load data into rows
+of a matrix. The <A HREF="#custom">default options</A> in include.h have been
+changed. If you are updating from a beta version of newmat09 look through the
+next section as there were some late changes to newmat09. </P>
+<P>If you are upgrading from <B>newmat08</B> note the following:
+</P>
+<UL>
+<LI>Boolean, TRUE, FALSE are now bool, true, false. See
+<A HREF="#custom">customising</A> if your compiler supports the bool class.
+</LI>
+<LI>ReDimension is now <A HREF="#dimen">ReSize</A>.  
+</LI>
+<LI>The <A HREF="#except">simulated exception</A> package has
+been updated. </LI>
+<LI>Operators <TT>==</TT>, <TT>!=</TT>, <TT>+=</TT>,
+<TT>-=</TT>, <TT>*=</TT>, <TT>|=</TT>, <TT>&amp;=</TT> are now supported as
+<A HREF="#binary">binary</A> matrix operators. </LI>
+<LI><TT>A+=f</TT>, <TT>A-=f</TT>, <TT>A*=f</TT>, <TT>A/=f</TT>,
+<TT>f+A</TT>, <TT>f-A</TT>, <TT>f*A</TT> are supported for <A HREF="#matscal">A
+matrix, f scalar</A>. </LI>
+<LI><A HREF="#trigtran">Fast trigonometric transforms</A>.
+</LI>
+<LI><A HREF="#unary">Reverse</A> function for reversing order of
+elements in a vector or matrix. </LI>
+<LI><A HREF="#scalar3">IsSingular</A> function. </LI>
+<LI>An option is included for defining <A
+HREF="#namesp">namespaces</A>. </LI>
+<LI>Dummy inequality operators are defined for compatibility
+with the STL. </LI>
+<LI>The row/column classes in newmat3.cpp have been modified to
+improve efficiency and correct an invalid use of pointer arithmetic. Most users
+won't be using these classes explicitly; if you are, please contact me for
+details of the changes. </LI>
+<LI>Matrix LU decomposition rewritten (faster for large arrays).
+</LI>
+<LI>The sort function rewritten (faster). </LI>
+<LI>The documentation files newmata.txt and newmatb.txt have
+been amalgamated and both are included in the hypertext version. </LI>
+<LI>Some of the <A HREF="#make">make</A> files reorganised
+again. </LI>
+</UL>
+<P>If you are upgrading from <B>newmat07</B> note the following:
+</P>
+<UL>
+<LI>.cxx files are now .cpp files. Some versions of won't accept
+.cpp. The <I>make</I> files for Gnu and AT&amp;T link the .cpp files to .cxx
+files before compilation and delete the links after compilation.  </LI>
+<LI>An <A HREF="#custom">option</A> in include.h allows you to
+use compiler supported exceptions, simulated exceptions or disable exceptions.
+Edit the file include.h to select one of these three options. Don't simulate
+exceptions if you have set your compiler's option to implement exceptions.
+</LI>
+<LI>New <A HREF="#qr">QR decomposition</A> functions.  
+</LI>
+<LI>A <A HREF="#nonlin">non-linear least squares</A> class.
+</LI>
+<LI>No need to explicitly set the AT&amp;T option in include.h.
+</LI>
+<LI><A HREF="#binary">Concatenation and elementwise
+multiplication</A>. </LI>
+<LI>A new <A HREF="#unspec">GenericMatrix</A> class.  
+</LI>
+<LI><A HREF="#scalar3">Sum</A> function. </LI>
+<LI>Some of the <A HREF="#make">make</A> files reorganised.
+</LI>
+</UL>
+<P>If you are upgrading from <B>newmat06</B> note the following:
+</P>
+<UL>
+<LI>If you are using &lt;&lt; to load a Real into a submatrix
+change this to =. </LI>
+</UL>
+<P>If you are upgrading from <B>newmat03</B> or <B>newmat04</B>
+note the following </P>
+<UL>
+<LI>.hxx files are now .h files </LI>
+<LI>real changed to Real </LI>
+<LI>BOOL changed to Boolean </LI>
+<LI>CopyToMatrix changed to AsMatrix, etc </LI>
+<LI>real(A) changed to A.AsScalar() </LI>
+</UL>
+<P>The current version is quite a bit longer that newmat04, so
+if you are almost out of space with newmat04, don't throw newmat04 away until
+you have checked your program will work under this version. </P>
+<P>See the <A HREF="#changes">change history</A> for other changes. </P>
+<h2><a name="except_1"></a>2.6 Catching exceptions</h2>
+<P CLASS="small"><A HREF="#example">next</A> - <A HREF="#example">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>This section applies particularly to people using <i>compiler supported</i>
+exceptions rather than my <i>simulated</i> exceptions. </P>
+<P>If newmat detects an error it will throw an exception. It is important that
+you catch this exception and print the error message. Otherwise you will get an
+unhelpful message like <i>abnormal termination</i>. I suggest you set up your
+main program like&nbsp; </P>
+<pre>#define WANT_STREAM             // or #include &lt;iostream&gt;
+#include &quot;include.h&quot;            // or #include &quot;newmat.h&quot;
+#include &quot;myexcept.h&quot;
+
+main()
+{
+   try
+   {
+      ... your program here
+   }
+   // catch exceptions thrown by my programs
+   catch(Exception) { cout &lt;&lt; Exception::what() &lt;&lt; endl; }
+   // catch exceptions thrown by other people's programs
+   catch(...) { cout &lt;&lt; &quot;exception caught in main program&quot; &lt;&lt; endl; }
+   return 0;
+}</pre>
+<P>If you are using a GUI version rather a console version of the program you
+will need to replace the <i>cout </i>statements by windows pop-up messages.</P>
+<P>If you are using my simulated exceptions or have set the disable exceptions
+option in <i>include.h</i> then uncaught exceptions automatically print the
+error message generated by the exception so you can ignore this section.
+Alternatively use <i>Try</i>, <i>Catch</i> and <i>CatchAll</i> in place of <i>try</i>, <i>catch</i>
+and <i>catch(...)</i> in the preceding code.</P>
+<P>See the <a href="#except">section on exceptions</a> for more information on
+the exception structure. </P>
+<H2><A NAME="example"></A>2.7 Example</H2>
+<P CLASS="small"><A HREF="#testing">next</A> - <A HREF="#testing">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>An example is given in <TT>example.cpp</TT>. This gives a simple linear
+regression example using five different algorithms. The correct output is given
+in <TT>example.txt</TT>. The program carries out a rough check that no memory
+is left allocated on the heap when it terminates. See the section on
+<A HREF="#testing">testing</A> for a comment on the reliability of this check
+and the use of the DO_FREE_CHECK option. </P>
+<P>I include a variety of make files. To compile the example use a command like
+</P>
+<pre>   gmake -f nm_gnu.mak example              (Gnu G++)
+   gmake -f nm_cc.mak example               (AT&amp;T, HPUX, Sun)
+   make -f nm_b55.mak example.exe           (Borland C++ 5.5)</pre>
+<p>You can generate make make files for a number of other compilers with my
+<a href="genmake.htm">genmake</a> utility.</p>
+
+<P>To compile all the example and test files use a command like </P>
+<PRE>   gmake -f nm_gnu.mak                      (Gnu G++)
+</PRE>
+
+<P>  The example uses io manipulators. It will not work with a
+compiler that does not support the standard io manipulators. </P>
+<P>Other example files are <TT>nl_ex.cpp</TT> and <TT>garch.cpp</TT> for
+demonstrating the non-linear fitting routines, <TT>sl_ex</TT> for demonstrating
+the solve function and <TT>test_exc</TT> for demonstrating the exceptions. </P>
+<H2><A NAME="testing"></A>2.8 Testing</H2>
+<P CLASS="small"><A HREF="#bugs">next</A> - <A HREF="#bugs">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>The library package contains a comprehensive test program in the form of a
+series of files with names of the form tmt?.cxx. The files consist of a large
+number of matrix formulae all of which evaluate to zero (except the first one
+which is used to check that we are detecting non-zero matrices). The printout
+should state that it has found just one non-zero matrix. </P>
+<P>The test program should be run with <I>Real</I> typedefed to <I>double</I>
+rather than <I>float</I> in <A HREF="#custom">include.h</A>. </P>
+<P>Make sure the <A HREF="#elements">C subscripts</A> are enabled if you want
+to test these. </P>
+<P>If you are carrying out some form of bounds checking, for example, with
+Borland's <I>CodeGuard</I>, then disable the testing of the <A
+HREF="#nric">Numerical Recipes in C</A> interface. Activate the statement
+<TT>#define DONT_DO_NRIC</TT> in tmt.h. </P>
+<P>Various versions of the make file (extension .mak) are included with the
+package. See the section on <A HREF="#make">make files</A>. </P>
+<P>The program also allocates and deletes a large block and small block of
+memory before it starts the main testing and then at the end of the test. It
+then checks that the blocks of memory were allocated in the same place. If not,
+then one suspects that there has been a memory leak. i.e. a piece of memory has
+been allocated and not deleted.</P>
+<P>This is not  foolproof. Programs may allocate extra print buffers
+while the program is running. I have tried to overcome this by doing a print
+before I allocate the first memory block. Programs may allocate memory for
+different sized items in different places, or might not allocate items
+consecutively. Or they might mix the items with memory blocks from other
+programs. Nevertheless, I seem to get consistent answers from <i>some</i> of the
+compilers I work with, so I think this is a worthwhile test. The compilers that 
+the test seems to work for include the Borland compilers, Microsoft VC++ 6 , 
+Watcom 10a, and Gnu 2.96 for Linux.</P>
+<P>If the <A HREF="#custom">DO_FREE_CHECK</A> option in include.h is activated,
+the program checks that each <TT>new</TT> is balanced with exactly one
+<TT>delete</TT>. This provides a more definitive test of no memory leaks. There
+are additional statements in myexcept.cpp which can be activated to print out
+details of the memory being allocated and released. </P>
+<P>I have included a facility for checking that each piece of code in the
+library is really exercised by the test routines. Each block of code in the
+main part of the library contains a word <TT>REPORT</TT>. <TT>newmat.h</TT> has
+a line defining <TT>REPORT</TT> that can be activated (deactivate the dummy
+version). This gives a printout of the number of times each of the
+<TT>REPORT</TT> statements in the <TT>.cpp</TT> files is accessed. Use a grep
+with line numbers to locate the lines on which <TT>REPORT</TT> occurs and
+compare these with the lines that the printout shows were actually accessed.
+One can then see which lines of code were not accessed. </P>
+<H2><A NAME="bugs"></A>2.9 Bugs</H2>
+<P CLASS="small"><a href="#problemareas">next</a> - <a href="#problemareas">skip</a> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A> </P>
+<UL>
+<LI>Small memory leaks may occur when an exception is thrown and caught. </LI>
+<LI>My exception scheme may not be not properly linked in with the standard
+library exceptions. In particular, my scheme may fail to catch out-of-memory
+exceptions.</LI>
+</UL>
+<h2><a name="problemareas"></a>2.10 Problem areas</h2>
+<P CLASS="small"><A HREF="#files">next</A> - <A HREF="#files">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A> </P>
+<p>This section lists parts of <i>Newmat</i> which users (including me) have found 
+difficult or unnatural. Also see the <a href="nmfaq.htm">newmat FAQ list</a> on 
+my <a href="#where">website</a>.</p>
+<p><b>Invert, element access, matrix multiply etc causes the program to crash</b></p>
+<blockquote>
+<p CLASS="small">Newmat throws an exception when it detects an error. This can cause a program 
+crash unless the exception is caught with a <i>catch</i> statement. See
+<a href="#except_1">catching exceptions</a>.</p>
+</blockquote>
+<p><b><tt>1x1</tt> matrix not automatically converted to a Real</b></p>
+<blockquote>
+<p CLASS="small">Use the <a href="#ch_type">AsScalar()</a> member function or the
+<a href="#scalar3">DotProduct() function</a> to take the dot 
+product of two vectors.</p>
+</blockquote>
+<p><b>Constructors do not initialise elements</b></p>
+<blockquote>
+<p CLASS="small">For example, <tt>Matrix A(4,5);</tt> does not initialise the elements of <tt>A</tt>. Use the 
+statement <tt>A=0.0</tt> to set the values to zero.</p>
+</blockquote>
+<p><b><i>ReSize</i> does not initialise elements</b></p>
+<blockquote>
+<p CLASS="small">For example, <tt>A.ReSize(5,6);</tt> does not set the elements of <tt>A</tt>. 
+See <a href="#dimen">ReSize</a>.</p>
+</blockquote>
+<p><b>Setting Matrix to a scalar sets all the values</b></p>
+<blockquote>
+<p CLASS="small"><tt>A(1,3) = 0.0;</tt> sets one element of a Matrix to zero. <tt>A = 0.0;</tt> sets all the 
+elements to zero. This is very convenient but also a source of error that is 
+ 
+hard to see if you wanted <tt>A(1,3) = 0.0;</tt> but left out the element details.</p>
+</blockquote>
+<p><b>Symmetry not detected automatically</b></p>
+<blockquote>
+<p CLASS="small">For example, <tt>SymmetricMatrix SM = A.t() * A;</tt> will fail. Use <tt>SymmetricMatrix 
+SM; SM &lt;&lt; A.t() * A;</tt></p>
+</blockquote>
+<p><b>Multiple multiplication may be inefficient</b></p>
+<blockquote>
+<p CLASS="small">For example, <tt>A * B * X</tt> where <tt>A</tt> and <tt>B</tt> are matrices and <tt>X</tt> is a column vector is 
+likely to be much slower than <tt>A * (B * X)</tt>.</p>
+</blockquote>
+<p>&nbsp;</p>
+<H2><A NAME="files"></A>2.11 List of files</H2>
+<P CLASS="small"><A HREF="#problem">next</A> - <A HREF="#problem">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH="100%" BORDER="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" cellpadding="0">
+<TR>
+<TD width="25%"><B>Documentation</B></TD>
+<TD width="25%">readme.txt</TD>
+<TD width="50%">readme file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm11.htm</TD>
+<TD width="50%">documentation file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">add_time.pgn</TD>
+<TD width="50%">image used by nm11.htm</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">rbd.css</TD>
+<TD width="50%">style sheet for nm11.htm</TD>
+</TR>
+<TR>
+<TD width="25%"><B>Definition files</B></TD>
+<TD width="25%">controlw.h</TD>
+<TD width="50%">control word definition file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">include.h</TD>
+<TD width="50%">details of include files and options</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">myexcept.h</TD>
+<TD width="50%">general exception handler definitions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat.h</TD>
+<TD width="50%">main matrix class definition file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatap.h</TD>
+<TD width="50%">applications definition file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatio.h</TD>
+<TD width="50%">input/output definition file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatnl.h</TD>
+<TD width="50%">non-linear optimisation definition file</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatrc.h</TD>
+<TD width="50%">row/column functions definition files</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatrm.h</TD>
+<TD width="50%">rectangular matrix access definition files</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">precisio.h</TD>
+<TD width="50%">numerical precision constants</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">solution.h</TD>
+<TD width="50%">one dimensional solve definition file</TD>
+</TR>
+<TR>
+<TD width="25%"><B>Program files</B></TD>
+<TD width="25%">bandmat.cpp</TD>
+<TD width="50%">band matrix routines</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">cholesky.cpp</TD>
+<TD width="50%">Cholesky decomposition</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">evalue.cpp</TD>
+<TD width="50%">eigenvalues and eigenvector calculation</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">fft.cpp</TD>
+<TD width="50%">fast Fourier, trig. transforms</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">hholder.cpp</TD>
+<TD width="50%">QR routines</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">jacobi.cpp</TD>
+<TD width="50%">eigenvalues by the Jacobi method</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">myexcept.cpp</TD>
+<TD width="50%">general error and exception handler</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newfft.cpp</TD>
+<TD width="50%">new fast Fourier transform</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat1.cpp</TD>
+<TD width="50%">type manipulation routines</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat2.cpp</TD>
+<TD width="50%">row and column manipulation functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat3.cpp</TD>
+<TD width="50%">row and column access functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat4.cpp</TD>
+<TD width="50%">constructors, resize, utilities</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat5.cpp</TD>
+<TD width="50%">transpose, evaluate, matrix functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat6.cpp</TD>
+<TD width="50%">operators, element access</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat7.cpp</TD>
+<TD width="50%">invert, solve, binary operations</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat8.cpp</TD>
+<TD width="50%">LU decomposition, scalar functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat9.cpp</TD>
+<TD width="50%">output routines</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatex.cpp</TD>
+<TD width="50%">matrix exception handler</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatnl.cpp</TD>
+<TD width="50%">non-linear optimisation</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmatrm.cpp</TD>
+<TD width="50%">rectangular matrix access functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">sort.cpp</TD>
+<TD width="50%">sorting functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">solution.cpp</TD>
+<TD width="50%">one dimensional solve</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">submat.cpp</TD>
+<TD width="50%">submatrix functions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">svd.cpp</TD>
+<TD width="50%">singular value decomposition</TD>
+</TR>
+<TR>
+<TD width="25%"><B>Example files</B></TD>
+<TD width="25%">example.cpp</TD>
+<TD width="50%">example of use of package</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">example.txt</TD>
+<TD width="50%">output from example</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">sl_ex.cpp</TD>
+<TD width="50%">example of OneDimSolve routine</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">sl_ex.txt</TD>
+<TD width="50%">output from example</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nl_ex.cpp</TD>
+<TD width="50%">example of non-linear least squares</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nl_ex.txt</TD>
+<TD width="50%">output from example</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">garch.cpp</TD>
+<TD width="50%">example of maximum-likelihood fit</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">garch.dat</TD>
+<TD width="50%">data file for garch.cpp</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">garch.txt</TD>
+<TD width="50%">output from example</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">test_exc.cpp</TD>
+<TD width="50%">demonstration exceptions</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">test_exc.txt</TD>
+<TD width="50%">output from test_exc.cpp</TD>
+</TR>
+<TR>
+<TD width="25%"><B>Test files</B></TD>
+<TD width="25%">tmt.h</TD>
+<TD width="50%">header file for test files</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">tmt*.cpp</TD>
+<TD width="50%">test files (see the section on <A
+HREF="#testing">testing</A>)</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">tmt.txt</TD>
+<TD width="50%">output from test files</TD>
+</TR>
+<TR>
+<TD width="25%"><B>Make files</B></TD>
+<TD width="25%">nm_gnu.mak</TD>
+<TD width="50%">make file for Gnu G++</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_cc.mak</TD>
+<TD width="50%">make file for AT&amp;T, Sun and HPUX</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_b55.mak</TD>
+<TD width="50%">make file for Borland C++ 5.5</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_b56.mak</TD>
+<TD width="50%">make file for Borland Builder C++ 6</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_m6.mak</TD>
+<TD width="50%">make file for VC++ 6&amp;7</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_i5.mak</TD>
+<TD width="50%">make file for Intel C++ under Windows</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_il5.mak</TD>
+<TD width="50%">make file for Intel C++ under Linux</TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">newmat.lfl</TD>
+<TD width="50%">library file list for use with <a href="genmake.htm">genmake</a></TD>
+</TR>
+<TR>
+<TD width="25%">&nbsp;</TD>
+<TD width="25%">nm_targ.txt</TD>
+<TD width="50%">target file list for use with <a href="genmake.htm">genmake</a></TD>
+</TR>
+</TABLE>
+<H2><A NAME="problem"></A>2.12 Problem report form
+</H2>
+<P CLASS="small"><A HREF="#refer">next</A> - <A HREF="#refer">skip</A> -
+<A HREF="#starting">up</A> - <A HREF="#top">start</A></P>
+<P>Copy and paste this to your editor; fill it out and email to
+<B>robert (at) statsresearch.co.nz</B> </P>
+<P>But first look in my web page <a href="http://www.robertnz.net">
+http://www.robertnz.net</a> to see if the bug has
+already been reported. </P>
+<PRE> Version: ............... newmat11 (28 March 2004)
+ Your email address: ....
+ Today's date: ..........
+ Your machine: ..........
+ Operating system: ......
+ Compiler &amp; version: ....
+ Compiler options
+   (eg GUI or console)...
+ Describe the problem - attach examples if possible:
+
+
+
+
+
+-----------------------------------------------------------
+</PRE>
+
+<H2><A NAME="refer"></A>3. Reference manual</H2>
+<P CLASS="small"><A HREF="#constr">next</A> - <A HREF="#error">skip</A> -
+<A HREF="#top">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH="100%">
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#constr">3.1
+Constructors </A><BR>
+<A HREF="#elements">3.2 Accessing elements </A><BR>
+<A HREF="#copy">3.3 Assignment and copying </A><BR>
+<A HREF="#entering">3.4 Entering values </A><BR>
+<A HREF="#unary">3.5 Unary operations </A><BR>
+<A HREF="#binary">3.6 Binary operations </A><BR>
+<A HREF="#matscal">3.7 Matrix and scalar ops </A><BR>
+<A HREF="#scalar1">3.8 Scalar functions - size &amp; shape </A><BR>
+<A HREF="#scalar2">3.9 Scalar functions - maximum &amp; minimum </A><BR>
+<A HREF="#scalar3">3.10 Scalar functions - numerical </A><BR>
+<A HREF="#submat">3.11 Submatrices </A><BR>
+<A HREF="#dimen">3.12 Change dimension </A><BR>
+<A HREF="#ch_type">3.13 Change type </A><BR>
+<A HREF="#solve">3.14 Multiple matrix solve </A><BR>
+<A HREF="#memory">3.15 Memory management </A><BR>
+<A HREF="#efficien">3.16 Efficiency</A><br>
+<A
+HREF="#output">3.17 Output</A></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%">  
+<A HREF="#unspec">3.18 Accessing unspecified type </A><BR>
+<A HREF="#cholesky">3.19 Cholesky decomposition </A><BR>
+<A HREF="#qr">3.20 QR decomposition </A><BR>
+<A HREF="#svd">3.21 Singular value decomposition </A><BR>
+<A HREF="#evalues">3.22 Eigenvalue decomposition </A><BR>
+<A HREF="#sorting">3.23 Sorting </A><BR>
+<A HREF="#fft">3.24 Fast Fourier transform </A><BR>
+<A HREF="#trigtran">3.25 Fast trigonometric transforms </A><BR>
+<A HREF="#nric">3.26 Numerical recipes in C </A><BR>
+<A HREF="#except">3.27 Exceptions </A><BR>
+<A HREF="#cleanup">3.28 Cleanup following exception </A><BR>
+<A HREF="#nonlin">3.29 Non-linear applications </A><BR>
+<A HREF="#stl">3.30 Standard template library </A><BR>
+<A HREF="#namesp">3.31 Namespace </A><br>
+<a href="#upd_chol">3.32 Updating the Cholesky matrix</a><br>
+<a href="#RealStarStar">3.33 Accessing C functions</a><br>
+<a href="#SimpleIntArray">3.34 Simple integer array class</a></TD>
+</TR>
+</TABLE>
+<H2><A NAME="constr"></A>3.1 Constructors</H2>
+<P CLASS="small"><A HREF="#elements">next</A> - <A HREF="#elements">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>To construct an <I>m</I> x <I>n</I> matrix, <TT>A</TT>, (<I>m</I> and
+<I>n</I> are integers) use </P>
+<PRE>    Matrix A(m,n);
+</PRE>
+
+<P>The SquareMatrix, UpperTriangularMatrix, LowerTriangularMatrix, SymmetricMatrix and
+DiagonalMatrix types are square. To construct an <I>n</I> x <I>n</I> matrix
+use, for example </P>
+<PRE>    SquareMatrix SQ(n);
+    UpperTriangularMatrix UT(n);
+    LowerTriangularMatrix LT(n);
+    SymmetricMatrix S(n);
+    DiagonalMatrix D(n);
+</PRE>
+
+<P>Band matrices need to include bandwidth information in their constructors. 
+</P>
+<PRE>    BandMatrix BM(n, lower, upper);
+    UpperBandMatrix UB(n, upper);
+    LowerBandMatrix LB(n, lower);
+    SymmetricBandMatrix SB(n, lower);
+</PRE>
+
+<P>The integers <I>upper</I> and <I>lower</I> are the number of non-zero
+diagonals above and below the diagonal (<I>excluding</I> the diagonal)
+respectively. </P>
+<P>The RowVector and ColumnVector types take just one argument in their
+constructors: </P>
+<PRE>    RowVector RV(n);
+    ColumnVector CV(n);
+</PRE>
+
+<P><b>These constructors do <EM>not</EM> initialise the elements of the matrices.
+</b>
+To set all the elements to zero use, for example, </P>
+<PRE>    Matrix A(m, n); A = 0.0;
+</PRE>
+
+<P>The IdentityMatrix takes one argument in its constructor specifying its 
+dimension.</P>
+<pre>    IdentityMatrix I(n);</pre>
+<p>The value of the diagonal elements <b>is</b> set to 1 by default, but you can 
+change this value as with other matrix types. </p>
+
+<P>You can also construct vectors and matrices without specifying the
+dimension. For example </P>
+<PRE>    Matrix A;
+</PRE>
+
+<P>In this case the dimension must be set by an <A HREF="#copy">assignment
+statement</A> or a <A HREF="#dimen">re-size statement</A>. </P>
+<P>You can also use a constructor to set a matrix equal to another matrix or
+matrix expression. </P>
+<PRE>    Matrix A = UT;
+    Matrix A = UT * LT;
+</PRE>
+
+<P>Only conversions that don't lose information are supported - eg you cannot
+convert an upper triangular matrix into a diagonal matrix using =. </P>
+<H2><A NAME="elements"></A>3.2 Accessing elements 
+</H2>
+<P CLASS="small"><A HREF="#copy">next</A> - <A HREF="#copy">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>Elements are accessed by expressions of the form <TT>A(i,j)</TT> where
+<I>i</I> and <I>j</I> run from 1 to the appropriate dimension. Access elements
+of vectors with just one argument. Diagonal matrices can accept one or two
+subscripts. </P>
+<P>This is different from the earliest version of the package in which the
+subscripts ran from 0 to one less than the appropriate dimension. Use
+<TT>A.element(i,j)</TT> if you want this earlier convention. </P>
+<P><TT>A(i,j)</TT> and <TT>A.element(i,j)</TT> can appear on either side of an
+= sign. </P>
+<P>If you activate the <TT>#define SETUP_C_SUBSCRIPTS</TT> in
+<TT>include.h</TT> you can also access elements using the traditional C style
+notation. That is <TT>A[i][j]</TT> for matrices (except diagonal) and
+<TT>V[i]</TT> for vectors and diagonal matrices. The subscripts start at zero
+(i.e. like element) and there is <I>no</I> range checking. Because of the
+possibility of confusing <TT>V(i)</TT> and <TT>V[i]</TT>, I suggest you do
+<I>not</I> activate this option unless you really want to use it.</P>
+<P>Symmetric matrices are stored as lower triangular matrices. It is important
+to remember this if you are using the <TT>A[i][j]</TT> method of accessing
+elements. Make sure the first subscript is greater than or equal to the second
+subscript. However, if you are using the <TT>A(i,j)</TT> method the program
+will swap <TT>i</TT> and <TT>j</TT> if necessary; so it doesn't matter if you
+think of the storage as being in the upper triangle (but it <I>does</I> matter
+in some other situations such as when <A HREF="#entering">entering</A> data).</P>
+<P>The IdentityMatrix type does not support element access.</P>
+<P>For interfacing with traditional C functions that involve one and two 
+dimensional arrays see <a href="#RealStarStar">accessing C functions</a>.</P>
+<H2><A NAME="copy"></A>3.3 Assignment and copying</H2>
+<P CLASS="small"><A HREF="#entering">next</A> - <A HREF="#entering">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The operator <TT>=</TT> is used for copying matrices, converting matrices,
+or evaluating expressions. For example </P>
+<PRE>    A = B;  A = L;  A = L * U;
+</PRE>
+
+<P>Only conversions that don't lose information are supported. The dimensions
+of the matrix on the left hand side are adjusted to those of the matrix or
+expression on the right hand side. Elements on the right hand side which are
+not present on the left hand side are set to zero. </P>
+<P>The operator <TT>&lt;&lt;</TT> can be used in place of <TT>=</TT> where it
+is permissible for information to be lost. </P>
+<P>For example </P>
+<PRE>    SymmetricMatrix S; Matrix A;
+    ......
+    S &lt;&lt; A.t() * A;
+</PRE>
+
+<P>is acceptable whereas </P>
+<PRE>    S = A.t() * A;                            // error
+</PRE>
+
+<P>will cause a runtime error since the package does not (yet?) recognise
+<TT>A.t()*A</TT> as symmetric. </P>
+<P>Note that you can <I>not</I> use <TT>&lt;&lt;</TT> with constructors. For
+example </P>
+<PRE>    SymmetricMatrix S &lt;&lt; A.t() * A;           // error
+</PRE>
+
+<P>does <I>not</I> work. </P>
+<P>Also note that <TT>&lt;&lt;</TT> cannot be used to load values from a full
+matrix into a band matrix, since it will be unable to determine the bandwidth
+of the band matrix. </P>
+<P>A third copy routine is used in a similar role to <TT>=</TT>. Use </P>
+<PRE>    A.Inject(D);
+</PRE>
+
+<P>to copy the elements of <TT>D</TT> to the corresponding elements of
+<TT>A</TT> but leave the elements of <TT>A</TT> unchanged if there is no
+corresponding element of <TT>D</TT> (the <TT>=</TT> operator would set them to
+0). This is useful, for example, for setting the diagonal elements of a matrix
+without disturbing the rest of the matrix. Unlike <TT>=</TT> and
+<TT>&lt;&lt;</TT>, Inject does not reset the dimensions of <TT>A</TT>, which
+must match those of <TT>D</TT>. Inject does <I>not</I> test for no loss of
+information. </P>
+<P>You cannot replace <TT>D</TT> by a matrix expression. The effect of
+<TT>Inject(D)</TT> depends on the type of <TT>D</TT>. If <TT>D</TT> is an
+expression it might not be obvious to the user what type it would have. So I
+thought it best to disallow expressions. </P>
+<P>Inject can be used for loading values from a regular matrix into a band
+matrix. (Don't forget to zero any elements of the left hand side that will not
+be set by the loading operation). </P>
+<P>Both <TT>&lt;&lt;</TT> and Inject can be used with submatrix expressions on
+the left hand side. See the section on <A HREF="#submat">submatrices</A>. </P>
+<P>To set the elements of a matrix to a scalar use operator <TT>=</TT> </P>
+<PRE>    Real r; int m,n;
+    ......
+    Matrix A(m,n); A = r;</PRE>
+
+
+To swap the values in two matrices <tt>A</tt> and <tt>B</tt> use one of the 
+following expressions<pre>   A.swap(B);</pre>
+<pre>   swap(A,B);</pre>
+The matrices <tt>A</tt> and <tt>B</tt> must be of the same type. This can be any 
+of the matrix types listed in the <a href="#constr">section on constructors</a>,
+<a href="#solve">CroutMatrix, BandLUMatrix</a> or <a href="#unspec">
+GenericMatrix</a>. Swap works by switching pointers and does not do any actual copying 
+of the main data arrays.<p>Notes:</p>
+
+<ul>
+  <li>When you do a matrix assignment to another matrix or matrix expression with 
+either <tt>=</tt> or <tt>&lt;&lt;</tt> the original data array associated with the matrix 
+  being assigned to is destroyed 
+even if there is no change in length. See the section on <a href="#stor">storage</a>. 
+This means, in particular, that pointers to matrix elements - e.g.
+<tt>Real* a; a = &amp;(A(1,1));</tt> become invalid. If you want avoid this you 
+  can use 
+<tt>Inject</tt> rather than <tt>=</tt>. But remember that you may need to zero 
+  the matrix first.<br>
+  </li>
+</ul>
+
+<H2><A NAME="entering"></A>3.4 Entering values</H2>
+<P CLASS="small"><A HREF="#unary">next</A> - <A HREF="#unary">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>You can load the elements of a matrix from an array: </P>
+<PRE>    Matrix A(3,2);
+    Real a[] = { 11,12,21,22,31,33 };
+    A &lt;&lt; a;</PRE>
+<p>or</p>
+<pre>    Matrix A(3,2);
+    int a[] = { 11,12,21,22,31,33 };
+    A &lt;&lt; a;</pre>
+<p>This construction does <I>not</I> check that the numbers of elements match
+correctly. This version of <TT>&lt;&lt;</TT> can be used with submatrices on
+the left hand side. It is not defined for band matrices. </p>
+<P>Alternatively you can enter short lists using a sequence of numbers
+separated by <TT>&lt;&lt;</TT> . </P>
+<PRE>    Matrix A(3,2);
+    A &lt;&lt; 11 &lt;&lt; 12
+      &lt;&lt; 21 &lt;&lt; 22
+      &lt;&lt; 31 &lt;&lt; 32;
+</PRE>
+
+<P>This does check for the correct total number of entries, although the
+message for there being insufficient numbers in the list may be delayed until
+the end of the block or the next use of this construction. This does <I>not</I>
+work for band matrices or for long lists. It does work for submatrices if the
+submatrix is a single complete row. For example </P>
+<PRE>    Matrix A(3,2);
+    A.Row(1) &lt;&lt; 11 &lt;&lt; 12;
+    A.Row(2) &lt;&lt; 21 &lt;&lt; 22;
+    A.Row(3) &lt;&lt; 31 &lt;&lt; 32;
+</PRE>
+
+<P>Load only values that are actually stored in the matrix. For example </P>
+<PRE>    SymmetricMatrix S(2);
+    S.Row(1) &lt;&lt; 11;
+    S.Row(2) &lt;&lt; 21 &lt;&lt; 22;
+</PRE>
+
+<P>Try to restrict this way of loading data to numbers. You can include
+expressions, but these must not call a function which includes the same
+construction. </P>
+
+<p>Remember that matrices are stored by rows and that symmetric matrices are
+stored as <I> lower</I> triangular matrices when using these methods to enter
+data. </p>
+<H2><A NAME="unary"></A>3.5 Unary operators</H2>
+<P CLASS="small"><A HREF="#binary">next</A> - <A HREF="#binary">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The package supports unary operations </P>
+<PRE>    X = -A;           // change sign of elements
+    X = A.t();        // transpose
+    X = A.i();        // inverse (of square matrix A)
+    X = A.Reverse();  // reverse order of elements of vector
+                      // or matrix (not band matrix)
+</PRE>
+
+<H2><A NAME="binary"></A>3.6 Binary operators</H2>
+<P CLASS="small"><A HREF="#matscal">next</A> - <A HREF="#matscal">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The package supports binary operations </P>
+<PRE>    X = A + B;       // matrix addition
+    X = A - B;       // matrix subtraction
+    X = A * B;       // matrix multiplication
+    X = A.i() * B;   // equation solve (square matrix A)
+    X = A | B;       // concatenate horizontally (concatenate the rows)
+    X = A &amp; B;       // concatenate vertically (concatenate the columns)
+    X = SP(A, B);    // elementwise product of A and B (Schur product)
+    X = KP(A, B);    // Kronecker product of A and B
+    X = CrossProduct(A, B);          // vector cross product - see notes
+    X = CrossProductRows(A, B);      // cross product of rows
+    X = CrossProductColumns(A, B);   // cross product of columns
+    bool b = A == B; // test whether A and B are equal
+    bool b = A != B; // ! (A == B)
+    A += B;          // A = A + B;
+    A -= B;          // A = A - B;
+    A *= B;          // A = A * B;
+    A |= B;          // A = A | B;
+    A &amp;= B;          // A = A &amp; B;
+    &lt;, &gt;, &lt;=, &gt;=     // included for compatibility with STL - see notes
+</PRE>
+
+<P>Notes: </P>
+<UL>
+<LI>If you are doing repeated multiplication. For example <TT>A*B*C</TT>, use
+brackets to force the order of evaluation to minimise the number of operations.
+If <TT>C</TT> is a column vector and <TT>A</TT> is not a vector, then it will
+usually reduce the number of operations to use <TT>A*(B*C)</TT>. </LI>
+<LI>In the equation solve example case the inverse is not explicitly
+calculated. An LU decomposition of <TT>A</TT> is performed and this is applied
+to <TT>B</TT>. This is more efficient than calculating the inverse and then
+multiplying. See also <A HREF="#solve">multiple matrix solving</A>. </LI>
+<LI>The package does not (yet?) recognise <TT>B*A.i()</TT> as an equation solve
+and the inverse of <TT>A</TT> would be calculated. It is probably better to use
+<TT>(A.t().i()*B.t()).t()</TT>. </LI>
+<LI>Horizontal or vertical concatenation returns a result of type Matrix,
+RowVector or ColumnVector. </LI>
+<LI>If <TT>A</TT> is <I> m</I> x <I>p</I>, <TT>B</TT> is <I> m</I> x <I>q</I>,
+then <TT>A | B</TT> is <I> m</I> x (<I>p</I>+<I>q</I>) with the <I>k</I>-th row
+being the elements of the <I>k</I>-th row of <TT>A</TT> followed by the
+elements of the <I>k</I>-th row of <TT>B</TT>. </LI>
+<LI>If <TT>A</TT> is <I> p</I> x <I>n</I>, <TT>B</TT> is <I> q</I> x <I>n</I>,
+then <TT>A &amp; B</TT> is (<I>p</I>+<I>q</I>) x <I> n</I> with the <I>k</I>-th
+column being the elements of the <I>k</I>-th column of <TT>A</TT> followed by
+the elements of the <I>k</I>-th column of <TT>B</TT>. </LI>
+<LI>For complicated concatenations of matrices, consider instead using
+<A HREF="#submat">submatrices</A>. </LI>
+<LI>See the section on <A HREF="#submat">submatrices</A> on using a submatrix
+on the RHS of an expression.</LI>
+<LI>CrossProduct - assumes A and B are both RowVectors of length 3 or both 
+ColumnVectors of length 3. Result is a Matrix of same dimension as A or B (will 
+automatically convert to RowVector if A and B are RowVectors and ColumnVector if 
+they are ColumnVectors).</LI>
+<LI>CrossProductRows - assumes A and B are of type Matrix with the same number 
+of rows and 3 columns. Does a cross product on corresponding pairs of rows.</LI>
+<LI>CrossProductColumns - assumes A and B are of type Matrix with&nbsp; the same 
+number of columns and 3 rows. Does a cross product on corresponding pairs of 
+columns.</LI>
+<LI>Two matrices are equal if their difference is zero. They may be of
+different types. For the CroutMatrix or BandLUMatrix they must be of the same
+type and have all their elements equal. This is not a very useful operator and
+is included for compatibility with some container templates. </LI>
+<LI>The inequality operators are included for compatibility with some versions 
+of the
+<A HREF="#stl">standard template library</A>. If actually called, they will
+throw an exception. So don't try to sort a <I>list</I> of matrices. </LI>
+<LI> A row vector multiplied by a column vector yields a 1x1 matrix, <I>not</I>
+a Real. To get a Real result use either <A HREF="#scalar3"> AsScalar or
+DotProduct</A>. </LI>
+<LI> The result from Kronecker product, <tt>KP(A, B)</tt>, possesses an attribute such as 
+upper triangular, lower triangular, band, symmetric, diagonal if both of the 
+matrices <TT>A</TT> and <TT>B</TT> have the attribute. If <TT>A</TT> is band and <TT>B</TT> is a square type 
+(eg SquareMatrix, Diagonal, LowerTriangularMatrix etc) then 
+the result is band. </LI>
+</UL>
+<P CLASS="small">Remember that the product of symmetric matrices is not
+necessarily symmetric so the following code will not run:</P>
+<PRE>   SymmetricMatrix A, B;
+   .... put values in A, B ....
+   SymmetricMatrix C = A * B;   // run time error</PRE>
+
+<P CLASS="small">Use instead</P>
+<PRE>   Matrix C = A * B;</PRE>
+
+<P CLASS="small">or, if you <EM>know</EM> the product will be symmetric,
+use</P>
+<PRE>   SymmetricMatrix C; C &lt;&lt; A * B;
+</PRE>
+
+<H2><A NAME="matscal"></A>3.7 Matrix and scalar</H2>
+<P CLASS="small"><A HREF="#scalar1">next</A> - <A HREF="#scalar1">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The following expressions multiply the elements of a matrix <TT>A</TT> by a
+scalar <TT>f</TT>: <TT>A * f</TT> or <TT>f * A</TT> . Likewise one can divide
+the elements of a matrix <TT>A</TT> by a scalar <TT>f</TT>: <TT>A / f</TT> . 
+</P>
+<P>The expressions <TT>A + f</TT> and <TT>A - f</TT> add or subtract a
+rectangular matrix of the same dimension as <TT>A</TT> with elements equal to
+<TT>f</TT> to or from the matrix <TT>A</TT> . </P>
+<P>The expression <TT>f + A</TT> is an alternative to <TT>A + f</TT>. The
+expression <TT>f - A</TT> subtracts matrix <TT>A</TT> from a rectangular matrix
+of the same dimension as <TT>A</TT> and with elements equal to <TT>f</TT> . 
+</P>
+<P>The expression <TT>A += f</TT> replaces <TT>A</TT> by <TT>A + f</TT>.
+Operators <TT>-=</TT>, <TT>*=</TT>, <TT>/=</TT> are similarly defined. </P>
+<H2><A NAME="scalar1"></A>3.8 Scalar functions of a
+matrix - size &amp; shape</H2>
+<P CLASS="small"><A HREF="#scalar2">next</A> - <A HREF="#scalar2">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>This page describes functions returning the values associated with the size
+and shape of matrices. The following pages describe other scalar matrix
+functions. </P>
+<PRE>    int m = A.nrows();                     // number of rows
+    int m = A.Nrows();                     // number of rows
+    int n = A.ncols();                     // number of columns
+    int n = A.Ncols();                     // number of columns
+    MatrixType mt = A.Type();              // type of matrix
+    Real* s = A.data();                    // pointer to array of elements
+    const Real* s = A.data();              // pointer to array of elements
+                                           //    where A is const
+    const Real* s = A.const_data();        // pointer to array of elements
+    Real* s = A.Store();                   // pointer to array of elements
+    int l = A.size();                      // length of array of elements
+    int l = A.Storage();                   // length of array of elements
+    MatrixBandWidth mbw = A.BandWidth();   // upper and lower bandwidths
+</PRE>
+
+<P><TT>MatrixType mt = A.Type()</TT> returns the type of a matrix. Use
+<TT>(char*)mt</TT> to get a string (UT, LT, Rect, Sym, Diag, Band, UB, LB,
+Crout, BndLU) showing the type (Vector types are returned as Rect). </P>
+<P><TT>MatrixBandWidth</TT> has member functions <TT>Upper()</TT> and
+<TT>Lower()</TT> for finding the upper and lower bandwidths (number of
+diagonals above and below the diagonal, both zero for a diagonal matrix). For
+non-band matrices -1 is returned for both these values. </P>
+<H2><A NAME="scalar2"></A>3.9 Scalar functions of a
+matrix - maximum &amp; minimum</H2>
+<P CLASS="small"><A HREF="#scalar3">next</A> - <A HREF="#scalar3">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>This page describes functions for finding the maximum and minimum elements
+of a matrix. </P>
+<PRE>    int i, j;
+    Real mv = A.MaximumAbsoluteValue();    // maximum of absolute values
+    Real mv = A.MinimumAbsoluteValue();    // minimum of absolute values
+    Real mv = A.Maximum();                 // maximum value
+    Real mv = A.Minimum();                 // minimum value
+    Real mv = A.MaximumAbsoluteValue1(i);  // maximum of absolute values
+    Real mv = A.MinimumAbsoluteValue1(i);  // minimum of absolute values
+    Real mv = A.Maximum1(i);               // maximum value
+    Real mv = A.Minimum1(i);               // minimum value
+    Real mv = A.MaximumAbsoluteValue2(i,j);// maximum of absolute values
+    Real mv = A.MinimumAbsoluteValue2(i,j);// minimum of absolute values
+    Real mv = A.Maximum2(i,j);             // maximum value
+    Real mv = A.Minimum2(i,j);             // minimum value
+</PRE>
+
+<P>All these functions throw an exception if <TT>A</TT> has no rows or no
+columns. </P>
+<P>The versions <TT>A.MaximumAbsoluteValue1(i)</TT>, etc return the location of
+the extreme element in a RowVector, ColumnVector or DiagonalMatrix. The
+versions <TT>A.MaximumAbsoluteValue2(i,j)</TT>, etc return the row and column
+numbers of the extreme element. If the extreme value occurs more than once the
+location of the last one is given. </P>
+<P>The versions MaximumAbsoluteValue(A), MinimumAbsoluteValue(A), Maximum(A),
+Minimum(A) can be used in place of A.MaximumAbsoluteValue(),
+A.MinimumAbsoluteValue(), A.Maximum(), A.Minimum(). </P>
+<H2><A NAME="scalar3"></A>3.10 Scalar functions of a
+matrix - numerical</H2>
+<P CLASS="small"><A HREF="#submat">next</A> - <A HREF="#submat">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<PRE>    Real r = A.AsScalar();                 // value of 1x1 matrix
+    Real ssq = A.SumSquare();              // sum of squares of elements
+    Real sav = A.SumAbsoluteValue();       // sum of absolute values
+    Real s = A.Sum();                      // sum of values
+    Real norm = A.Norm1();                 // maximum of sum of absolute
+                                              values of elements of a column
+    Real norm = A.NormInfinity();          // maximum of sum of absolute
+                                              values of elements of a row
+    Real norm = A.NormFrobenius();         // square root of sum of squares
+                                           // of the elements
+    Real t = A.Trace();                    // trace
+    Real d = A.Determinant();              // determinant
+    LogAndSign ld = A.LogDeterminant();    // log of determinant
+    bool z = A.IsZero();                   // test all elements zero
+    bool s = A.IsSingular();               // A is a CroutMatrix or
+                                              BandLUMatrix
+    Real s = DotProduct(A, B);             // dot product of A and B
+                                           // interpreted as vectors
+</PRE>
+
+<P><TT>A.LogDeterminant()</TT> returns a value of type LogAndSign. If ld is of
+type LogAndSign use </P>
+<PRE>    ld.Value()    to get the value of the determinant
+    ld.Sign()     to get the sign of the determinant (values 1, 0, -1)
+    ld.LogValue() to get the log of the absolute value.
+</PRE>
+
+<P>Note that the direct use of the function <TT>Determinant()</TT> will often
+cause a floating point overflow exception. </P>
+<P><TT>A.IsZero()</TT> returns Boolean value <TT>true</TT> if the matrix
+<TT>A</TT> has all elements equal to 0.0. </P>
+<P><TT>IsSingular</TT> is defined only for CroutMatrix and BandLUMatrix. It
+returns <TT>true</TT> if one of the diagonal elements of the LU decomposition
+is exactly zero. </P>
+<P><TT>DotProduct(const Matrix&amp; A,const Matrix&amp; B)</TT> converts both
+of the arguments to rectangular matrices, checks that they have the same number
+of elements and then calculates the first element of <TT>A * </TT>first element
+of <TT>B + </TT>second element of <TT>A * </TT>second element of <TT>B +
+...</TT> ignoring the row/column structure of <TT>A</TT> and <TT>B</TT>. It is
+primarily intended for the situation where <TT>A</TT> and <TT>B</TT> are row or
+column vectors. </P>
+<P>The versions Sum(A), SumSquare(A), SumAbsoluteValue(A), Trace(A),
+LogDeterminant(A), Determinant(A), Norm1(A), NormInfinity(A), NormFrobenius(A)
+can be used in place of A.Sum(), A.SumSquare(), A.SumAbsoluteValue(),
+A.Trace(), A.LogDeterminant(), A.Norm1(), A.NormInfinity(), A.NormFrobenius(). 
+</P>
+<H2><A NAME="submat"></A>3.11 Submatrices</H2>
+<P CLASS="small"><A HREF="#dimen">next</A> - <A HREF="#dimen">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<PRE>    A.SubMatrix(fr,lr,fc,lc)
+</PRE>
+
+<P>This selects a submatrix from <TT>A</TT>. The arguments
+<TT>fr</TT>,<TT>lr</TT>,<TT>fc</TT>,<TT>lc</TT> are the first row, last row,
+first column, last column of the submatrix with the numbering beginning at 1. 
+</P>
+<P>I allow <TT>lr = fr-1</TT> or <TT>lc = fc-1</TT> or to indicate that a
+matrix of zero rows or columns is to be returned. </P>
+<P>A submatrix command may be used in any matrix expression or on the left hand
+side of <TT>=</TT>, <TT>&lt;&lt;</TT> or Inject. Inject does <I>not</I> check
+no information loss. You can also use the construction </P>
+<PRE>    Real c; .... A.SubMatrix(fr,lr,fc,lc) = c;
+</PRE>
+
+<P>to set a submatrix equal to a constant. </P>
+<P>The following are variants of SubMatrix: </P>
+<PRE>    A.SymSubMatrix(f,l)             //   This assumes fr=fc and lr=lc.
+    A.Rows(f,l)                     //   select rows
+    A.Row(f)                        //   select single row
+    A.Columns(f,l)                  //   select columns
+    A.Column(f)                     //   select single column
+</PRE>
+
+<P>In each case <TT>f</TT> and <TT>l</TT> mean the first and last row or column
+to be selected (starting at 1). </P>
+<P>I allow <TT>l = f-1</TT> to indicate that a matrix of zero rows or columns
+is to be returned. </P>
+<P>If SubMatrix or its variant occurs on the right hand side of an <TT>=</TT>
+or <TT>&lt;&lt;</TT> or within an expression think of its type as follows </P>
+<PRE>    A.SubMatrix(fr,lr,fc,lc)           If A is RowVector or
+                                       ColumnVector then same type
+                                       otherwise type Matrix
+    A.SymSubMatrix(f,l)                Same type as A
+    A.Rows(f,l)                        Type Matrix
+    A.Row(f)                           Type RowVector
+    A.Columns(f,l)                     Type Matrix
+    A.Column(f)                        Type ColumnVector
+</PRE>
+
+<P>If SubMatrix or its variant appears on the left hand side of <TT>=</TT> or
+<TT>&lt;&lt;</TT> , think of its type being Matrix. Thus <TT>L.Row(1)</TT>
+where <TT>L</TT> is LowerTriangularMatrix expects <TT>L.Ncols()</TT> elements
+even though it will use only one of them. If you are using <TT>=</TT> the
+program will check for no loss of data.</P>
+
+<P>A SubMatrix can appear on the left-hand side of <TT>+=</TT> or <TT>-=</TT>
+with a matrix expression on the right-hand side. It can also appear on the
+left-hand side of <TT>+=</TT>, <TT>-=</TT>, <TT>*=</TT> or <TT>/=</TT> with a
+Real on the right-hand side. In each case there must be no loss of information.
+</P>
+<P>The <TT>Row</TT> version can appear on the left hand side of
+<TT>&lt;&lt;</TT> for <A HREF="#entering">loading literal data</A> into a row.
+Load only the number of elements that are actually going to be stored in
+memory. </P>
+<P>Do not use the <TT>+=</TT> and <TT>-=</TT> operations with a submatrix of a
+SymmetricMatrix or BandSymmetricMatrix on the LHS and a Real on the RHS.</P>
+<P>You can't pass a submatrix (or any of its variants) as a reference 
+non-constant matrix in a function argument. For example, the following will not 
+work:</P>
+<pre>   void YourFunction(Matrix&amp; A);
+   ...
+   Matrix B(10,10);
+   YourFunction(B.SubMatrix(1,5,1,5))    // won't compile</pre>
+<P>If you are are using the submatrix facility to build a matrix from a small
+number of components, consider instead using the <A
+HREF="#binary">concatenation operators</A>. </P>
+<H2><A NAME="dimen"></A>3.12 Change dimensions</H2>
+<P CLASS="small"><A HREF="#ch_type">next</A> - <A HREF="#ch_type">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The following operations change the dimensions of a matrix. The values of
+the elements are lost. </P>
+<PRE>    A.ReSize(nrows,ncols);        // for type Matrix or nricMatrix
+    A.ReSize(n);                  // for all other types, except Band
+    A.ReSize(n,lower,upper);      // for BandMatrix
+    A.ReSize(n,lower);            // for LowerBandMatrix
+    A.ReSize(n,upper);            // for UpperBandMatrix
+    A.ReSize(n,lower);            // for SymmetricBandMatrix
+    A.ReSize(B);                  // set dims to those of B 
+</PRE>
+
+<P>Use <TT>A.CleanUp()</TT> to set the dimensions of <TT>A</TT> to zero and
+release all the heap memory. </P>
+<P><TT>A.ReSize(B)</TT> sets the dimensions of <TT>A</TT> to those of a matrix
+<TT>B</TT>. This includes the band-width in the case of a band matrix. It is an
+error for <TT>A</TT> to be a band matrix and <TT>B</TT> not a band matrix (or
+diagonal matrix). </P>
+<P>Remember that <TT>ReSize</TT> destroys values. If you want to
+<TT>ReSize</TT>, but keep the values in the bit that is left use something like
+</P>
+<PRE>   ColumnVector V(100);
+   ...                            // load values
+   V = V.Rows(1,50);              // to get first 50 values.
+</PRE>
+
+<P>If you want to extend a matrix or vector use something like </P>
+<PRE>   ColumnVector V(50);
+   ...                            // load values
+   { V.Release(); ColumnVector X=V; V.ReSize(100); V.Rows(1,50)=X; }
+                                  // V now length 100
+</PRE>
+
+<H2><A NAME="ch_type"></A>3.13 Change type</H2>
+<P CLASS="small"><A HREF="#solve">next</A> - <A HREF="#solve">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The following functions interpret the elements of a matrix (stored row by
+row) to be a vector or matrix of a different type. Actual copying is usually
+avoided where these occur as part of a more complicated expression. </P>
+<PRE>    A.AsRow()
+    A.AsColumn()
+    A.AsDiagonal()
+    A.AsMatrix(nrows,ncols)
+    A.AsScalar()
+</PRE>
+
+<P>The expression <TT>A.AsScalar()</TT> is used to convert a 1 x 1 matrix to a
+scalar. </P>
+<H2><A NAME="solve"></A>3.14 Multiple matrix solve</H2>
+<P CLASS="small"><A HREF="#memory">next</A> - <A HREF="#memory">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>To solve the matrix equation <TT>Ay = b</TT> where <TT>A</TT> is a square
+matrix of equation coefficients, <TT>y</TT> is a column vector of values to be
+solved for, and <TT>b</TT> is a column vector, use the code </P>
+<PRE>    int n = something
+    Matrix A(n,n); ColumnVector b(n);
+    ... put values in A and b
+    ColumnVector y = A.i() * b;       // solves matrix equation
+</PRE>
+
+<P>The following notes are for the case where you want to solve more than one
+matrix equation with different values of <TT>b</TT> but the same <TT>A</TT>. Or
+where you want to solve a matrix equation and also find the determinant of
+<TT>A</TT>. In these cases you probably want to avoid repeating the LU
+decomposition of <TT>A</TT> for each solve or determinant calculation. </P>
+<P>If <TT>A</TT> is a square or symmetric matrix use </P>
+<PRE>    CroutMatrix X = A;                // carries out LU decomposition
+    Matrix AP = X.i()*P; Matrix AQ = X.i()*Q;
+    LogAndSign ld = X.LogDeterminant();
+</PRE>
+
+<P>rather than </P>
+<PRE>    Matrix AP = A.i()*P; Matrix AQ = A.i()*Q;
+    LogAndSign ld = A.LogDeterminant();
+</PRE>
+
+<P>since each operation will repeat the LU decomposition. </P>
+<P>If <TT>A</TT> is a BandMatrix or a SymmetricBandMatrix begin with </P>
+<PRE>    BandLUMatrix X = A;               // carries out LU decomposition
+</PRE>
+
+<P>A CroutMatrix or a BandLUMatrix can't be manipulated or copied. Use
+references as an alternative to copying. </P>
+<P>Alternatively use </P>
+<PRE>    LinearEquationSolver X = A;
+</PRE>
+
+<P>This will choose the most appropriate decomposition of <TT>A</TT>. That is,
+the band form if <TT>A</TT> is banded; the Crout decomposition if <TT>A</TT> is
+square or symmetric and no decomposition if <TT>A</TT> is triangular or 
+diagonal.</P>
+<H2><A NAME="memory"></A>3.15 Memory management</H2>
+<P CLASS="small"><A HREF="#efficien">next</A> - <A HREF="#efficien">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The package does not support delayed copy. Several strategies are required
+to prevent unnecessary matrix copies. </P>
+<P>Where a matrix is called as a function argument use a constant reference.
+For example </P>
+<PRE>    YourFunction(const Matrix&amp; A)
+</PRE>
+
+<P>rather than </P>
+<PRE>    YourFunction(Matrix A)
+</PRE>
+
+<P>Skip the rest of this section on your first reading. </P>
+<P>A second place where it is desirable to avoid unnecessary copies is when a
+function is returning a matrix. Matrices can be returned from a function with
+the return command as you would expect. However these may incur one and
+possibly two copyings of the matrix. To avoid this use the following
+instructions. </P>
+<P>Make your function of type ReturnMatrix . Then precede the return statement
+with a Release statement (or a ReleaseAndDelete statement if the matrix was
+created with new). For example </P>
+<PRE>    ReturnMatrix MakeAMatrix()
+    {
+       Matrix A;                // or any other matrix type
+       ......
+       A.Release(); return A;
+    }
+</PRE>
+
+<P>or </P>
+<PRE>    ReturnMatrix MakeAMatrix()
+    {
+       Matrix* m = new Matrix;
+       ......
+       m-&gt;ReleaseAndDelete(); return *m;
+    }
+</PRE>
+
+<P>If your compiler objects to this code, replace the return statements with 
+</P>
+<PRE>    return A.ForReturn();
+</PRE>
+
+<P>or </P>
+<PRE>    return m-&gt;ForReturn();
+</PRE>
+
+<P>If you are using AT&amp;T C++ you may wish to replace <TT>return A;</TT> by
+return <TT>(ReturnMatrix)A;</TT> to avoid a warning message; but this will give
+a runtime error with Gnu. (You can't please everyone.) </P>
+<HR>
+<P><B>Do not forget to make the function of type ReturnMatrix; otherwise you
+may get incomprehensible run-time errors.</B> </P>
+<HR>
+<P>You can also use <TT>.Release()</TT> or <TT>-&gt;ReleaseAndDelete()</TT> to
+allow a matrix expression to recycle space. Suppose you call </P>
+<PRE>    A.Release();
+</PRE>
+
+<P>just before <TT>A</TT> is used just once in an expression. Then the memory
+used by <TT>A</TT> is either returned to the system or reused in the
+expression. In either case, <TT>A</TT>'s memory is destroyed. This procedure
+can be used to improve efficiency and reduce the use of memory. </P>
+<P>Use <TT>-&gt;ReleaseAndDelete</TT> for matrices created by new if you want
+to completely delete the matrix after it is accessed. </P>
+<H2><A NAME="efficien"></A>3.16 Efficiency</H2>
+<P CLASS="small"><A HREF="#output">next</A> - <A HREF="#output">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The package tends to be not very efficient for dealing with matrices with
+short rows. This is because some administration is required for accessing rows
+for a variety of types of matrices. To reduce the administration a special
+multiply routine is used for rectangular matrices in place of the generic one.
+Where operations can be done without reference to the individual rows (such as
+adding matrices of the same type) appropriate routines are used. </P>
+<P>When you are using small matrices (say smaller than 10 x 10) you may find it
+faster to use rectangular matrices rather than the triangular or symmetric
+ones. </P>
+<H2><A NAME="output"></A>3.17 Output</H2>
+<P CLASS="small"><A HREF="#unspec">next</A> - <A HREF="#unspec">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>To print a matrix use an expression like </P>
+<PRE>   Matrix A;
+   ......
+   cout &lt;&lt; setw(10) &lt;&lt; setprecision(5) &lt;&lt; A;
+</PRE>
+
+<P>This will work only with systems that support the standard input/output
+routines including manipulators. You need to #include the files iostream.h,
+iomanip.h, newmatio.h in your C++ source files that use this facility. The
+files iostream.h, iomanip.h will be included automatically if you include the
+statement <TT>#define WANT_STREAM</TT> at the beginning of your source file. So
+you can begin your file with either </P>
+<PRE>   #define WANT_STREAM
+   #include &quot;newmatio.h&quot;
+</PRE>
+
+<P>or </P>
+<PRE>   #include &lt;iostream.h&gt;
+   #include &lt;iomanip.h&gt;
+   #include &quot;newmatio.h&quot;
+</PRE>
+
+<P>The present version of this routine is useful only for matrices small enough
+to fit within a page or screen width. </P>
+<P>To print several vectors or matrices in columns use a <A
+HREF="#binary">concatenation operator</A>: </P>
+<PRE>   ColumnVector A, B;
+   .....
+   cout &lt;&lt; setw(10) &lt;&lt; setprecision(5) &lt;&lt; (A | B);
+</PRE>
+
+<H2><A NAME="unspec"></A>3.18 Unspecified type</H2>
+<P CLASS="small"><A HREF="#cholesky">next</A> - <A HREF="#cholesky">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>Skip this section on your first reading. </P>
+<P>If you want to work with a matrix of unknown type, say in a function. You
+can construct a matrix of type <TT>GenericMatrix</TT>. Eg </P>
+<PRE>   Matrix A;
+   .....                                  // put some values in A
+   GenericMatrix GM = A;
+</PRE>
+
+<P>A GenericMatrix matrix can be used anywhere where a matrix expression can be
+used and also on the left hand side of an <TT>=</TT>. You can pass any type of
+matrix (excluding the Crout and BandLUMatrix types) to a <TT>const
+GenericMatrix&amp;</TT> argument in a function. However most scalar functions
+including nrows(), ncols(), Type() and element access do not work with it. Nor
+does the ReturnMatrix construct. <tt><a href="#copy">swap</a></tt> does work with objects of type 
+GenericMatrix. See also the paragraph on <A
+HREF="#solve">LinearEquationSolver</A>. </P>
+<P>An alternative and less flexible approach is to use BaseMatrix or
+GeneralMatrix. </P>
+<P>Suppose you wish to write a function which accesses a matrix of unknown type
+including expressions (eg <TT>A*B</TT>). Then use a layout similar to the
+following: </P>
+<PRE>   void YourFunction(BaseMatrix&amp; X)
+   {
+      GeneralMatrix* gm = X.Evaluate();   // evaluate an expression
+                                          // if necessary
+      ........                            // operations on *gm
+      gm-&gt;tDelete();                      // delete *gm if a temporary
+   }
+</PRE>
+
+<P>See, as an example, the definitions of <TT>operator&lt;&lt;</TT> in
+newmat9.cpp. </P>
+<P>Under certain circumstances; particularly where <TT>X</TT> is to be used
+just once in an expression you can leave out the <TT>Evaluate()</TT> statement
+and the corresponding <TT>tDelete()</TT>. Just use <TT>X</TT> in the
+expression. </P>
+<P>If you know YourFunction will never have to handle a formula as its argument
+you could also use </P>
+<PRE>   void YourFunction(const GeneralMatrix&amp; X)
+   {
+      ........                            // operations on X
+   }
+</PRE>
+
+<P>Do not try to construct a GeneralMatrix or BaseMatrix. </P>
+<H2><A NAME="cholesky"></A>3.19 Cholesky
+decomposition</H2>
+<P CLASS="small"><A HREF="#qr">next</A> - <A HREF="#qr">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>Suppose <TT>S</TT> is symmetric and positive definite. Then there exists a
+unique lower triangular matrix <TT>L</TT> such that <TT>L * L.t() = S</TT>. To
+calculate this use </P>
+<PRE>    SymmetricMatrix S;
+    ......
+    LowerTriangularMatrix L = Cholesky(S);
+</PRE>
+
+<P>If <TT>S</TT> is a symmetric band matrix then <TT>L</TT> is a band matrix
+and an alternative procedure is provided for carrying out the decomposition: 
+</P>
+<PRE>    SymmetricBandMatrix S;
+    ......
+    LowerBandMatrix L = Cholesky(S);</PRE>
+
+<p>See section <a href="#upd_chol">3.32</a> on updating a Cholesky 
+decomposition.<br>
+</p>
+
+<H2><A NAME="qr"></A>3.20 QR decomposition</H2>
+<P CLASS="small"><A HREF="#svd">next</A> - <A HREF="#svd">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>This is a variant on the usual QR transformation. </P>
+<P>Start with matrix (dimensions shown to left and below the matrix)</P>
+<PRE>       / 0    0 \      s
+       \ X    Y /      n
+
+         s    t
+</PRE>
+
+<P>Our version of the QR decomposition multiplies this matrix by an orthogonal
+matrix Q to get </P>
+<PRE>       / U    M \      s
+       \ 0    Z /      n
+
+         s    t
+</PRE>
+
+<P>where <TT>U</TT> is upper triangular (the R of the QR transform). That is 
+</P>
+<PRE>      Q  / 0   0 \  =  / U   M \
+         \ X   Y /     \ 0   Z / </PRE>
+
+<P>This is good for solving least squares problems: choose b (matrix or column
+vector) to minimise the sum of the squares of the elements of </P>
+<PRE>         Y - X*b
+</PRE>
+
+<P>Then choose <TT>b = U.i()*M;</TT> The residuals <TT>Y - X*b</TT> are in
+<TT>Z</TT>. </P>
+<P>This is the usual QR transformation applied to the matrix <TT>X</TT> with
+the square zero matrix concatenated on top of it. It gives the same triangular
+matrix as the QR transform applied directly to <TT>X</TT> and generally seems
+to work in the same way as the usual QR transform. However it fits into the
+matrix package better and also gives us the residuals directly. It turns out to
+be essentially a modified Gram-Schmidt decomposition. </P>
+<P>Two routines are provided in <I>newmat</I>: </P>
+<PRE>    QRZ(X, U);
+</PRE>
+
+<P>replaces <TT>X</TT> by orthogonal columns and forms <TT>U</TT>. </P>
+<PRE>    QRZ(X, Y, M);
+</PRE>
+
+<P>uses <TT>X</TT> from the first routine, replaces <TT>Y</TT> by <TT>Z</TT>
+and forms <TT>M</TT>. </P>
+<P>The are also two routines <TT>QRZT(X, L)</TT> and <TT>QRZT(X, Y, M)</TT>
+which do the same decomposition on the transposes of all these matrices. <tt>QRZT</tt>
+replaces the routines <tt>HHDecompose</tt> in earlier versions of <i>newmat</i>. 
+<tt>HHDecompose</tt> is
+still defined but just calls <tt>QRZT</tt>.</P>
+<P>For an example of the use of this decomposition see the file
+<A HREF="#example">example.cpp</A>. </P>
+<P>See section <a href="#upd_chol">3.32</a> on updating <tt>U</tt>.</P>
+<P>Alternatively to update <TT>U</TT> or <TT>L</TT> with a new block of data, <tt>X</tt>, one can use</P>
+<pre>    UpdateQRZ(X, U);
+</pre>
+<p>or</p>
+<pre>    UpdateQRZT(X, L);</pre>
+<p><b>Notes on UpdateQRZ and UpdateQRZT:</b></p>
+<ul>
+  <li>Use these routines if your data is arriving in blocks or there is too much to 
+fit into memory.</li>
+  <li>Use <TT>QRZ</TT> or <TT>QRZT</TT> on the first block of data or you can use <TT>UpdateQRZ</TT> or 
+<TT>UpdateQRZT</TT> if <TT>U</TT> or <TT>L</TT> is correctly dimensioned and set to zero.</li>
+  <li>The block of data, <tt>X</tt>, will be modified by these routines but the 
+modified data is probably not useful for further analysis.</li>
+  <li>The signs of <TT>U</TT> or <TT>L</TT> maybe the reverse of what you would 
+expect (i.e. you get the negative of what you get from the Cholesky 
+decomposition calculation). Usually this will not be a problem, but if it is, 
+replace <tt>U</tt> by <tt>-U</tt> if <tt>U(1,1)&lt;0</tt> or <tt>L</tt> by <tt>-L</tt> if 
+<tt>L(1,1)&lt;0</tt>.</li>
+  <li>To solve a least squares problem (assuming a row of <tt>X</tt> contains the <tt>m</tt> values of 
+the independent variables for an individual and <tt>Y</tt> is a column vector containing 
+the dependent values. Form <tt>XY</tt> = <tt>X|Y</tt> and calculate <tt>U</tt> using <tt>UpdateQRZ</tt> on blocks of <tt>XY</tt>. 
+Then the least squares estimate is <tt>U.SymSubMatrix(1,m).i() * 
+U.SubMatrix(1,m,m+1,m+1)</tt>. Square <tt>U(m+1,m+1)</tt> to get the residual 
+  sum of squares.</li>
+</ul>
+<p>&nbsp;</p>
+<H2><A NAME="svd"></A>3.21 Singular value
+decomposition</H2>
+<P CLASS="small"><A HREF="#evalues">next</A> - <A HREF="#evalues">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The singular value decomposition of an <I>m</I> x <I>n</I> <TT>Matrix</TT>
+<TT>A</TT> (where <I>m</I> &gt;= <I>n</I>) is a decomposition </P>
+<PRE>    A  = U * D * V.t()
+</PRE>
+
+<P>where <TT>U</TT> is <I>m</I> x <I>n</I> with <TT>U.t() * U</TT> equalling
+the identity, <TT>D</TT> is an <I>n</I> x <I>n </I><TT>DiagonalMatrix</TT> and
+<TT>V</TT> is an <I>n</I> x <I>n</I> orthogonal matrix (type <TT>Matrix</TT> in
+<I>Newmat</I>). </P>
+<P>Singular value decompositions are useful for understanding the structure of
+ill-conditioned matrices, solving least squares problems, and for finding the
+eigenvalues of <TT>A.t() * A</TT>. </P>
+<P>To calculate the singular value decomposition of <TT>A</TT> (with <I>m</I>
+&gt;= <I>n</I>) use one of </P>
+<PRE>    SVD(A, D, U, V);                  // U = A is OK
+    SVD(A, D);
+    SVD(A, D, U);                     // U = A is OK
+    SVD(A, D, U, false);              // U (can = A) for workspace only
+    SVD(A, D, U, V, false);           // U (can = A) for workspace only
+</PRE>
+
+<P>where <TT>A</TT>, <TT>U</TT> and <TT>V</TT> are of type <TT>Matrix</TT> and
+<TT>D</TT> is a <TT>DiagonalMatrix</TT>. The values of <TT>A</TT> are not
+changed unless <TT>A</TT> is also inserted as the third argument.</P>
+
+<P>The elements of <tt>D</tt> are sorted in <i>descending</i> order.</P>
+<P CLASS="small">Remember that the SVD decomposition is not completely unique. The signs of the elements in a column of <TT>U</TT> may be reversed
+if the signs in the corresponding column in <TT>V</TT> are reversed. If a
+number of the singular values are identical one can apply an orthogonal
+transformation to the corresponding columns of <TT>U</TT> and the corresponding
+columns of <TT>V</TT>.</P>
+<H2><A NAME="evalues"></A>3.22 Eigenvalue
+decomposition</H2>
+<P CLASS="small"><A HREF="#sorting">next</A> - <A HREF="#sorting">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>An eigenvalue decomposition of a SymmetricMatrix <TT>A</TT> is a
+decomposition </P>
+<PRE>    A  = V * D * V.t()
+</PRE>
+
+<P>where <TT>V</TT> is an orthogonal matrix (type <TT>Matrix</TT> in
+<I>Newmat</I>) and <TT>D</TT> is a DiagonalMatrix. </P>
+<P>Eigenvalue analyses are used in a wide variety of engineering, statistical
+and other mathematical analyses. </P>
+<P>The package includes two algorithms: Jacobi and Householder. The first is
+extremely reliable but much slower than the second. </P>
+<P>The code is adapted from routines in <I>Handbook for Automatic Computation,
+Vol II, Linear Algebra</I> by Wilkinson and Reinsch, published by Springer
+Verlag. </P>
+<PRE>    Jacobi(A,D,S,V);                  // A, S symmetric; S is workspace,
+                                      //    S = A is OK; V is a matrix
+    Jacobi(A,D);                      // A symmetric
+    Jacobi(A,D,S);                    // A, S symmetric; S is workspace,
+                                      //    S = A is OK
+    Jacobi(A,D,V);                    // A symmetric; V is a matrix
+
+    EigenValues(A,D);                 // A symmetric
+    EigenValues(A,D,S);               // A, S symmetric; S is for back
+                                      //    transforming, S = A is OK
+    EigenValues(A,D,V);               // A symmetric; V is a matrix
+</PRE>
+
+<P>where <TT>A</TT>, <TT>S</TT> are of type <TT>SymmetricMatrix</TT>,
+<TT>D</TT> is of type <TT>DiagonalMatrix</TT> and <TT>V</TT> is of type
+<TT>Matrix</TT>. The values of <TT>A</TT> are not changed unless <TT>A</TT> is
+also inserted as the third argument. If you need eigenvectors use one of the
+forms with matrix <TT>V</TT>. The eigenvectors are returned as the columns of
+<TT>V</TT>.</P>
+
+<P>The elements of <tt>D</tt> are sorted in <i>ascending</i> order.</P>
+<P CLASS="small">Remember that an eigenvalue decomposition is not completely
+unique - see the comments about the <A HREF="#svd">SVD</A>
+decomposition. </P>
+<H2><A NAME="sorting"></A>3.23 Sorting</H2>
+<P CLASS="small"><A HREF="#fft">next</A> - <A HREF="#fft">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>To sort the values in a matrix or vector, <TT>A</TT>, (in general this
+operation makes sense only for vectors and diagonal matrices) use one of</P>
+<PRE>    SortAscending(A);
+
+    SortDescending(A);
+</PRE>
+
+<P>I use the quicksort algorithm. The algorithm is similar to that in
+Sedgewick's algorithms in C++. If the sort seems to be failing (as quicksort
+can do) an exception is thrown. </P>
+<P>You will get incorrect results if you try to sort a band matrix - but why
+would you want to sort a band matrix? </P>
+<H2><A NAME="fft"></A>3.24 Fast Fourier transform 
+</H2>
+<P CLASS="small"><A HREF="#trigtran">next</A> - <A HREF="#trigtran">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<PRE>   FFT(X, Y, F, G);                         // F=X and G=Y are OK
+</PRE>
+
+<P>where <TT>X</TT>, <TT>Y</TT>, <TT>F</TT>, <TT>G</TT> are ColumnVectors.
+<TT>X</TT> and <TT>Y</TT> are the real and imaginary input vectors; <TT>F</TT>
+and <TT>G</TT> are the real and imaginary output vectors. The lengths of
+<TT>X</TT> and <TT>Y</TT> must be equal and should be the product of numbers
+less than about 10 for fast execution. </P>
+<P>The formula is </P>
+<PRE>          n-1
+   h[k] = SUM  z[j] exp (-2 pi i jk/n)
+          j=0
+</PRE>
+
+<P>where <TT>z[j]</TT> is stored complex and stored in <TT>X(j+1)</TT> and
+<TT>Y(j+1)</TT>. Likewise <TT>h[k]</TT> is complex and stored in
+<TT>F(k+1)</TT> and <TT>G(k+1)</TT>. The fast Fourier algorithm takes order <I>
+n</I> log(<I>n</I>) operations (for <I>good</I> values of <I>n</I>) rather than
+<I>n</I>**2 that straight evaluation (see the file <TT>tmtf.cpp</TT>) takes. 
+</P>
+<P>I use one of two methods: </P>
+<UL>
+<LI>A program originally written by Sande and Gentleman. This requires that
+<I>n</I> can be expressed as a product of small numbers.</LI>
+<LI>A method of Carl de Boor (1980), <I>Siam J Sci Stat Comput</I>, pp 173-8.
+The sines and cosines are calculated explicitly. This gives better accuracy, at
+an expense of being a little slower than is otherwise possible. This is slower
+than the Sande-Gentleman program but will work for all <I>n</I> --- although it
+will be very slow for <I>bad</I> values of <I>n</I>.</LI>
+</UL>
+<P>Related functions </P>
+<PRE>   FFTI(F, G, X, Y);                        // X=F and Y=G are OK
+   RealFFT(X, F, G);
+   RealFFTI(F, G, X);
+</PRE>
+
+<P><TT>FFTI</TT> is the inverse transform for <TT>FFT</TT>. <TT>RealFFT</TT> is
+for the case when the input vector is real, that is <TT>Y = 0</TT>. I assume
+the length of <TT>X</TT>, denoted by <I>n</I>, is <I>even</I>. That is,
+<I>n</I> must be divisible by 2. The program sets the lengths of <TT>F</TT> and
+<TT>G</TT> to <I>n</I>/2 + 1. <TT>RealFFTI</TT> is the inverse of
+<TT>RealFFT</TT>. </P>
+<P>See also the section on fast <A HREF="#trigtran">trigonometric
+transforms</A>.</P>
+<P>There  are also two dimensional versions</P>
+<pre>   FFT2(X, Y, F, G);                       // F=X and G=Y are OK
+   FFT2I(F, G, X, Y);                      // inverse, X=F and Y=G are OK</pre>
+<p>where <TT>X</TT>, <TT>Y</TT>, <TT>F</TT>, <TT>G</TT> are of type Matrix.
+<TT>X</TT> and <TT>Y</TT> are the real and imaginary input matrices; <TT>F</TT>
+and <TT>G</TT> are the real and imaginary output matrices. The dimensions of <TT>Y</TT> 
+must be the same as those of <TT>X</TT> and should be the product of numbers
+less than about 10 for fast execution. </p>
+<P>The formula is </P>
+<PRE>            m-1 n-1
+   h[p,q] = SUM SUM z[j,k] exp (-2 pi i (jp/m + kq/n))
+            j=0 k=0
+</PRE>
+
+<P>where <TT>z[j,k]</TT> is stored complex and stored in <TT>X(j+1,k+1)</TT> and
+<TT>Y(j+1,k+1)</TT> and <TT>X</TT> and <TT>Y</TT> have dimension <TT>m x n</TT>. Likewise <TT>h[p,q]</TT> is complex and stored in
+<TT>F(p+1,q+1)</TT> and <TT>G(p+1,q+1)</TT>. 
+</P>
+<P>&nbsp;</P>
+<H2><A NAME="trigtran"></A>3.25 Fast trigonometric
+transforms</H2>
+<P CLASS="small"><A HREF="#nric">next</A> - <A HREF="#nric">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>These are the sin and cosine transforms as defined by Charles Van Loan
+(1992) in <I>Computational frameworks for the fast Fourier transform</I>
+published by SIAM. See page 229. Some other authors use slightly different
+conventions. All the functions call the <A HREF="#fft">fast Fourier
+transforms</A> and require an <I> even</I> transform length, denoted by
+<I>m</I> in these notes. That is, <I>m</I> must be divisible by 2. As with the
+FFT <I>m</I> should be the product of numbers less than about 10 for fast
+execution. </P>
+<P>The functions I define are </P>
+<PRE>   DCT(U,V);                // U, V are ColumnVectors, length <I>m+1</I>
+   DCT_inverse(V,U);        // inverse of DCT
+   DST(U,V);                // U, V are ColumnVectors, length <I>m+1</I>
+   DST_inverse(V,U);        // inverse of DST
+   DCT_II(U,V);             // U, V are ColumnVectors, length <I>m</I>
+   DCT_II_inverse(V,U);     // inverse of DCT_II
+   DST_II(U,V);             // U, V are ColumnVectors, length <I>m</I>
+   DST_II_inverse(V,U);     // inverse of DST_II
+</PRE>
+
+<P>where the first argument is the input and the second argument is the output.
+<TT>V = U</TT> is OK. The length of the output ColumnVector is set by the
+functions. </P>
+<P>Here are the formulae: </P>
+<H3>DCT</H3>
+<PRE>                   m-1                             k
+   v[k] = u[0]/2 + SUM { u[j] cos (pi jk/m) } + (-) u[m]/2
+                   j=1
+</PRE>
+
+<P>for <TT>k = 0...m</TT>, where <TT>u[j]</TT> and <TT>v[k]</TT> are stored in
+<TT>U(j+1)</TT> and <TT>V(k+1)</TT>. </P>
+<H3>DST</H3>
+<PRE>          m-1
+   v[k] = SUM { u[j] sin (pi jk/m) }
+          j=1
+</PRE>
+
+<P>for <TT>k = 1...(m-1)</TT>, where <TT>u[j]</TT> and <TT>v[k]</TT> are stored
+in <TT>U(j+1)</TT> and <TT>V(k+1)</TT>and where <TT>u[0]</TT> and <TT>u[m]</TT>
+are ignored and <TT>v[0]</TT> and <TT>v[m]</TT> are set to zero. For the
+inverse function <TT>v[0]</TT> and <TT>v[m]</TT> are ignored and <TT>u[0]</TT>
+and <TT>u[m]</TT> are set to zero. </P>
+<H3>DCT_II</H3>
+<PRE>          m-1
+   v[k] = SUM { u[j] cos (pi (j+1/2)k/m) }
+          j=0
+</PRE>
+
+<P>for <TT>k = 0...(m-1)</TT>, where <TT>u[j]</TT> and <TT>v[k]</TT> are stored
+in <TT>U(j+1)</TT> and <TT>V(k+1)</TT>. </P>
+<H3>DST_II</H3>
+<PRE>           m
+   v[k] = SUM { u[j] sin (pi (j-1/2)k/m) }
+          j=1
+</PRE>
+
+<P>for <TT>k = 1...m</TT>, where <TT>u[j]</TT> and <TT>v[k]</TT> are stored in
+<TT>U(j)</TT> and <TT>V(k)</TT>. </P>
+<P>Note that the relationship between the subscripts in the formulae and those
+used in <I>newmat</I> is different for DST_II (and DST_II_inverse). </P>
+<H2><A NAME="nric"></A>3.26 Interface to Numerical
+Recipes in C</H2>
+<P CLASS="small"><A HREF="#except">next</A> - <A HREF="#except">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>This section refers to <i>Numerical Recipes in C</i>. This section is <b>not</b> 
+relevant to <i>Numerical Recipes in C++</i>. I'll put a note on the website soon 
+on how to interface with <i>Numerical Recipes in C++.</i></P>
+<P>This package can be used with the vectors and matrices defined in
+<I>Numerical Recipes in C</I>. You need to edit the routines in Numerical
+Recipes so that the elements are of the same type as used in this package. Eg
+replace float by double, vector by dvector and matrix by dmatrix, etc. You may
+need to edit the function definitions to use the version acceptable to your
+compiler (if you are using the first edition of NRIC). You may need to enclose
+the code from Numerical Recipes in <TT>extern &quot;C&quot; { ... }</TT>. You
+will also need to include the matrix and vector utility routines. </P>
+<P>Then any vector in Numerical Recipes with subscripts starting from 1 in a
+function call can be accessed by a RowVector, ColumnVector or DiagonalMatrix in
+the present package. Similarly any matrix with subscripts starting from 1 can
+be accessed by an nricMatrix in the present package. The class nricMatrix is
+derived from Matrix and can be used in place of Matrix. In each case, if you
+wish to refer to a RowVector, ColumnVector, DiagonalMatrix or nricMatrix
+<TT>X</TT> in an function from Numerical Recipes, use <TT>X.nric()</TT> in the
+function call. </P>
+<P>Numerical Recipes cannot change the dimensions of a matrix or vector. So
+matrices or vectors must be correctly dimensioned before a Numerical Recipes
+routine is called. </P>
+<P>For example </P>
+<PRE>   SymmetricMatrix B(44);
+   .....                             // load values into B
+   nricMatrix BX = B;                // copy values to an nricMatrix
+   DiagonalMatrix D(44);             // Matrices for output
+   nricMatrix V(44,44);              //    correctly dimensioned
+   int nrot;
+   jacobi(BX.nric(),44,D.nric(),V.nric(),&amp;nrot);
+                                     // jacobi from NRIC
+   cout &lt;&lt; D;                        // print eigenvalues
+</PRE>
+
+<H2><A NAME="except"></A>3.27 Exceptions</H2>
+<P CLASS="small"><A HREF="#cleanup">next</A> - <A HREF="#cleanup">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>Here is the class structure for exceptions: </P>
+<PRE>Exception
+  Logic_error
+    ProgramException                 miscellaneous matrix error
+    IndexException                   index out of bounds
+    VectorException                  unable to convert matrix to vector
+    NotSquareException               matrix is not square (invert, solve)
+    SubMatrixDimensionException      out of bounds index of submatrix
+    IncompatibleDimensionsException  (multiply, add etc)
+    NotDefinedException              operation not defined (eg &lt;)
+    CannotBuildException             copying a matrix where copy is undefined
+    InternalException                probably an error in newmat
+  Runtime_error
+    NPDException                     matrix not positive definite (Cholesky)
+    ConvergenceException             no convergence (e-values, non-linear, sort)
+    SingularException                matrix is singular (invert, solve)
+    SolutionException                no convergence in solution routine
+    OverflowException                floating point overflow
+  Bad_alloc                          out of space (new fails)
+</PRE>
+
+<P>I have attempted to mimic the exception class structure in the C++ standard
+library, by defining the Logic_error and Runtime_error classes. </P>
+<P>Suppose you have edited <tt>include.h</tt> to use my <i>simulated</i>
+exceptions or to <i>disable</i> exceptions. If there is no catch statement or exceptions are disabled then my
+<TT>Terminate()</TT> function in <TT>myexcept.h</TT> is called when you throw an
+exception. This prints out
+an error message, the dimensions and types of the matrices involved, the name
+of the routine detecting the exception, and any other information set by the
+<A HREF="#error">Tracer</A> class. Also see the section on <A
+HREF="#error">error messages</A> for additional notes on the messages generated
+by the exceptions. </P>
+<P>You can also print this information in a <i>catch</i> clause by printing <TT>Exception::what()</TT>. 
+</P>
+<P>If you are using <i> compiler supported</i> exceptions then see the section
+on <a href="#except_1">catching exceptions</a>.&nbsp; 
+</P>
+<P>See the file <TT>test_exc.cpp</TT> as an example of catching an exception
+and printing the error message. </P>
+<P>The 08 version of newmat defined a member function <TT>void
+SetAction(int)</TT> to help customise the action when an exception is called.
+This has been deleted in the 09 and 10 versions. Now include an instruction
+such as <TT>cout &lt;&lt; Exception::what() &lt;&lt; endl;</TT> in the
+<TT>Catch</TT> or <TT>CatchAll</TT> block to determine the action. </P>
+<P>The library includes the alternatives of using the inbuilt exceptions
+provided by a compiler, simulating exceptions, or disabling exceptions. See
+<A HREF="#custom">customising</A> for selecting the correct exception option. 
+</P>
+<P>The rest of this section describes my partial simulation of exceptions for
+compilers which do not support C++ exceptions. I use Carlos Vidal's article in
+the September 1992 <I>C Users Journal</I> as a starting point. </P>
+<P>Newmat does a partial clean up of memory following throwing an exception -
+see the next section. However, the present version will leave a little heap
+memory unrecovered under some circumstances. I would not expect this to be a
+major problem, but it is something that needs to be sorted out. </P>
+<P>The functions/macros I define are Try, Throw, Catch, CatchAll and
+CatchAndThrow. Try, Throw, Catch and CatchAll correspond to try, throw, catch
+and catch(...) in the C++ standard. A list of Catch clauses must be terminated
+by either CatchAll or CatchAndThrow but not both. Throw takes an Exception as
+an argument or takes no argument (for passing on an exception). I do not have a
+version of Throw for specifying which exceptions a function might throw. Catch
+takes an exception class name as an argument; CatchAll and CatchAndThrow don't
+have any arguments. Try, Catch and CatchAll must be followed by blocks enclosed
+in curly brackets. </P>
+<P>I have added another macro ReThrow to mean a rethrow, Throw(). This was
+necessary to enable the package to be compatible with both my exception package
+and C++ exceptions. </P>
+<P>If you want to throw an exception, use a statement like </P>
+<PRE>   Throw(Exception(&quot;Error message\n&quot;));
+</PRE>
+
+<P>It is important to have the exception declaration in the Throw statement,
+rather than as a separate statement. </P>
+<P>All exception classes must be derived from the class, Exception, defined in
+newmat and can contain only static variables. See the examples in newmat if you
+want to define additional exceptions.</P>
+<P>Note that the simulation exception mechanism does not work if you define
+arrays of matrices. </P>
+<H2><A NAME="cleanup"></A>3.28 Cleanup after an
+exception</H2>
+<P CLASS="small"><A HREF="#nonlin">next</A> - <A HREF="#nonlin">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>This section is about the simulated exceptions used in newmat. It is
+irrelevant if you are using the exceptions built into a compiler or have set
+the disable-exceptions option. </P>
+<P>The simulated exception mechanisms in newmat are based on the C functions
+setjmp and longjmp. These functions do not call destructors so can lead to
+garbage being left on the heap. (I refer to memory allocated by <I>new</I> as
+heap memory). For example, when you call </P>
+<PRE>   Matrix A(20,30);
+</PRE>
+
+<P>a small amount of space is used on the stack containing the row and column
+dimensions of the matrix and 600 doubles are allocated on the heap for the
+actual values of the matrix. At the end of the block in which A is declared,
+the destructor for A is called and the 600 doubles are freed. The locations on
+the stack are freed as part of the normal operations of the stack. If you leave
+the block using a longjmp command those 600 doubles will not be freed and will
+occupy space until the program terminates. </P>
+<P>To overcome this problem newmat keeps a list of all the currently declared
+matrices and its exception mechanism will return heap memory when you do a
+Throw and Catch. </P>
+<P>However it will not return heap memory from objects from other packages. 
+</P>
+<P>If you want the mechanism to work with another class you will have to do
+four things: </P>
+<OL>
+<LI>derive your class from class Janitor defined in except.h; </LI>
+<LI>define a function <TT>void CleanUp()</TT> in that class to return all heap
+memory; </LI>
+<LI>include the following lines in the class definition <PRE>      public:
+         void* operator new(size_t size)
+         { do_not_link=true; void* t = ::operator new(size); return t; }
+         void operator delete(void* t) { ::operator delete(t); }
+</PRE>
+
+</LI>
+<LI>be sure to include a copy constructor in you class definition, that is,
+something like <PRE>      X(const X&amp;);
+</PRE>
+
+</LI>
+</OL>
+<P>Note that the function <TT>CleanUp()</TT> does somewhat the same duties as
+the destructor. However <TT>CleanUp()</TT> has to do the <I>cleaning</I> for
+the class you are working with and also the classes it is derived from. So it
+will often be wrong to use exactly the same code for both <TT>CleanUp()</TT>
+and the destructor or to define your destructor as a call to
+<TT>CleanUp()</TT>. </P>
+<H2><A NAME="nonlin"></A>3.29 Non-linear
+applications</H2>
+<P CLASS="small"><A HREF="#stl">next</A> - <A HREF="#stl">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>Files solution.h, solution.cpp contain a class for solving for <I>x</I> in
+<I>y</I> = <I>f</I>(<I>x)</I> where <I>x</I> is a one-dimensional continuous
+monotonic function. This is not a matrix thing at all but is included because
+it is a useful program and because it is a simpler version of the coding technique used
+in the non-linear least squares. </P>
+<P>Files newmatnl.h, newmatnl.cpp contain a series of classes for non-linear
+least squares and maximum likelihood. These classes work on very well-behaved
+functions but need upgrading for less well-behaved functions. I haven't followed 
+the usual practice of inflating the values of the diagonal elements of the 
+matrix of second derivatives. I originally thought I could avoid this if my 
+program had a good line search. But this was wrong and when I use this program 
+on all but the most well-behaved problems I run the fit first with the diagonal 
+elements inflated by a factor of 2 to 5 and the critical value for the stopping 
+criterion set to something like 50. Then rerun with with no inflation factor and 
+critical value 0.0001.</P>
+<P>Documentation for both of these is in the definition files. Simple examples
+are in sl_ex.cpp, nl_ex.cpp and garch.cpp.</P>
+<H2><A NAME="stl"></A>3.30 Standard template
+library</H2>
+<P CLASS="small"><A HREF="#namesp">next</A> - <A HREF="#namesp">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P>The standard template library (STL) is the set of <I>container templates</I>
+(vector, deque, list etc) defined by the C++ standards committee. Newmat is
+intended to be compatible with the STL in the sense that you can store matrices
+in the standard containers. I have defined <A HREF="#binary"><TT>==</TT> and
+inequality </A>operators which seem to be required by some versions of the STL.</P>
+<P>If you want to use the container classes with Newmat please note </P>
+<UL>
+<LI>Don't use simulated exceptions. </LI>
+<LI>Make sure the option <A HREF="#custom">DO_FREE_CHECK</A> is <EM>not</EM>
+turned on. </LI>
+<LI>You can store only one type of matrix in a container. If you want to use a
+variety of types use the GenericMatrix type or store pointers to the matrices. 
+</LI>
+<LI>The vector and deque container templates like to copy their elements. For
+the vector container this happens when you insert an element anywhere except at
+the end or when you append an element and the current vector storage overflows.
+Since Newmat does not have <I>copy-on-write</I> this could get very inefficient. </LI>
+<LI>You won't be able to sort the container or do anything that would call an
+inequality operator. </LI>
+</UL>
+<H2><A NAME="namesp"></A>3.31 Namespace</H2>
+<P CLASS="small"><A HREF="#upd_chol">next</A> - <A HREF="#upd_chol">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></P>
+<P><I>Namespace</I> is used to avoid name
+clashes between different libraries. I have included the namespace capability.
+Activate the line <TT>#define use_namespace</TT> in <TT>include.h</TT>. Then
+include either the statement </P>
+<PRE>   using namespace NEWMAT;
+</PRE>
+
+<P>at the beginning of any file that needs to access the newmat library or </P>
+<PRE>   using namespace RBD_LIBRARIES;
+</PRE>
+
+<P>at the beginning of any file that needs to access all my libraries. </P>
+<P>This works correctly with <A HREF="#borland">Borland</A> C++ version 5 and 
+Builder 5 and 6. </P>
+<P><A HREF="#microso">Microsoft</A> Visual C++ version 5 works in my example
+and test files, but fails with apparently insignificant changes (it may be more
+reliable if you have applied service pack 3). If you #include
+&quot;newmatap.h&quot;, but no other newmat include file, then also #include
+&quot;newmatio.h&quot;. It seems to work with <A HREF="#microso">Microsoft</A>
+Visual C++ version 6 <I>if</I> you have applied at least service pack 2.</P>
+<P>My use of namespace does not work with <A HREF="#gcc">Gnu g++</A> version 
+2.8.1 but does work with versions 3.x. </P>
+<P>I have defined the following namespaces: </P>
+<UL>
+<LI>RBD_COMMON for functions and classes used by most of my libraries </LI>
+<LI>NEWMAT for the newmat library </LI>
+<LI>RBD_LIBRARIES for all my libraries </LI>
+</UL>
+<H2><A NAME="upd_chol"></A>3.32 Updating the Cholesky matrix</H2>
+
+
+<p CLASS="small"><A HREF="#RealStarStar">next</A> - <A HREF="#RealStarStar">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></p>
+
+
+<p>Suppose <tt>X</tt> is matrix and <tt>U</tt> has been formed with either</p>
+
+
+<pre>   SymmetricMatrix A; A &lt;&lt; X.t() * X;
+   UpperTriangularMatrix U = Cholesky(A).t();</pre>
+<p>or</p>
+<pre>   UpperTriangularMatrix U;
+   QRZ(X, U);</pre>
+<p>See sections <a href="#cholesky">3.19</a> and <a href="#qr">3.20</a>.</p>
+<p>Now suppose we want to append an extra row to <tt>X</tt> or delete a row from <tt>X</tt> 
+or rearrange the columns of <tt>X.</tt> The functions described here allow you to 
+update <tt>U</tt> without&nbsp;&nbsp;recalculating it.</p>
+
+
+<pre>   UpdateCholesky(U, x);                    // x is a RowVector
+   DowndateCholesky(U, x);                  // x is a RowVector
+   RightCircularUpdateCholesky(U, j, k);    // j and k are integers
+   LeftCircularUpdateCholesky(U, j, k);     // j and k are integers</pre>
+<p><tt>UpdateCholesky</tt> carries out the modification of <tt>U</tt> corresponding to appending 
+an extra row <tt>x</tt> to <tt>X</tt>.</p>
+
+
+<p> <tt>DowndateCholesky</tt> carries out the modification corresponding 
+to removing a row <tt>x</tt> from <tt>X</tt>. A <tt>ProgramException</tt> exception is 
+thrown if the modification fails.</p>
+
+
+<p><tt>RightCircularUpdateCholesky</tt> supposes that columns <tt>j,j+1,...k</tt> of <tt>X</tt> are 
+replaced by columns <tt>k,j,j+1,...k-1</tt>.</p>
+
+
+<p><tt>LeftCircularUpdateCholesky</tt> supposes that columns <tt>j,j+1,...k</tt> of <tt>X</tt> are replaced 
+by columns <tt>j+1,...k,j</tt>.</p>
+
+
+<p>These functions are based on a contribution from Nick Bennett of 
+Schlumberger-Doll Research. See also the LINPACK User's Guide, Chapter 10, 
+Dongarra et. al., SIAM, Philadelphia, 1979.</p>
+
+
+<p>Where you want to append a number of new rows consider using the update 
+routine in section <a href="#qr">3.20</a>.</p>
+
+
+<h2><a name="RealStarStar"></a>3.33 Accessing C functions</h2>
+
+
+<p CLASS="small"><A HREF="#SimpleIntArray">next</A> - <A HREF="#SimpleIntArray">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></p>
+
+
+<p>You have a <i>C</i> function that uses one and two dimensional arrays as 
+vectors and matrices. You want to access it from <i>Newmat</i>.</p>
+
+
+<p>One dimensional arrays are easy. Set up a <i>ColumnVector</i>, <i>RowVector</i> 
+or <i>DiagonalMatrix</i> with the correct dimension and where the function has a
+<tt>double*</tt> argument enter <tt>X.data()</tt> where <tt>X</tt> denotes the <i>
+ColumnVector</i>, <i>RowVector</i> or <i>DiagonalMatrix</i>. (I am assuming you 
+have left <i>Real</i> being <i>typedef</i>ed as a <i>double</i>). If you have a
+<tt>const double*</tt> argument use <tt>X.const_data()</tt>.</p>
+
+
+<p>You can't do this with two dimensional arrays where you have a <tt>double**</tt> 
+argument. <i>Newmat</i> includes  classes <i>RealStarStar</i> and <i>ConstRealStarStar</i> for this situation. 
+To access a <tt>Matrix A</tt> with from a function <tt>c_function(double** a)</tt> 
+use either</p>
+
+
+<pre>   c_function(RealStarStar(A));</pre>
+<p>or</p>
+<pre>   RealStarStar a(A);
+   c_function(a);</pre>
+<p>If the argument is <tt>const double**</tt> use <i>ConstRealStarStar</i>.</p>
+
+
+<p>The <tt>Matrix A</tt> must be&nbsp;correctly dimensioned and must not be 
+resized or set equal to another matrix between setting up the <i>RealStarStar</i> 
+object and its use in the function. Also the following construction will not 
+work</p>
+
+
+<pre>   double** a = RealStarStar(A);      // wrong
+   c_function(a);</pre>
+<p>since the <i>RealStarStar</i> structure will have been destroyed before you 
+get to the second line.</p>
+
+
+<h2><a name="SimpleIntArray"></a>3.34 Simple integer array class</h2>
+
+
+<p CLASS="small"><A HREF="#error">next</A> - <A HREF="#error">skip</A> -
+<A HREF="#refer">up</A> - <A HREF="#top">start</A></p>
+
+
+<p>This is primarily for use within <i>Newmat</i>. You can set up a simple array 
+of integers with the <i>SimpleIntArray</i> class. Here are the descriptions of 
+the constructors and functions.</p>
+
+
+<TABLE WIDTH=100%>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>SimpleIntArray A;</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> Constructs int array of length zero</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>SimpleIntArray A(n);</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> Constructs int array of length <i>n</i> - 
+individual elements are <i>not</i> initialised</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>A = i;</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> sets values to <i>i</i> where <i>i</i> is an int 
+variable</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>A = B;</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> sets values to those of <i>B</i> where 
+<i>B</i> is 
+a SimpleIntArray, change size if necessary.</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>n = A.size();</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> return the length of <i>A</i></TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>A.resize(n);</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> change the length of <i>A</i>, don't keep 
+values</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>A.resize(n, true);</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> change the length of <i>A</i>, do keep 
+values</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>int x = A[i];</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> element access; <i>i</i> runs from 0 to 
+<i>n</i>-1</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>int* d = A.data();</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> get beginning of data array</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>const int* d = A.data();</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> get beginning of data array as const 
+int* if <i>A</i> is const</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <tt>const int* d = A.const_data();</tt></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> get beginning of data array as const 
+int*</TD>
+</TR>
+</TABLE>
+
+
+<H2><A NAME="error"></A>4. Error messages</H2>
+<P CLASS="small"><A HREF="#design">next</A> - <A HREF="#design">skip</A> -
+<A HREF="#top">up</A> - <A HREF="#top">start</A></P>
+<P>Most error messages are self-explanatory. The message gives the size of the
+matrices involved. Matrix types are referred to by the following codes: </P>
+<PRE>   Matrix or vector                   Rect
+   Symmetric matrix                   Sym
+   Band matrix                        Band
+   Symmetric band matrix              SmBnd
+   Lower triangular matrix            LT
+   Lower triangular band matrix       LwBnd
+   Upper triangular matrix            UT
+   Upper triangular band matrix       UpBnd
+   Diagonal matrix                    Diag
+   Crout matrix (LU matrix)           Crout
+   Band LU matrix                     BndLU
+</PRE>
+
+<P>Other codes should not occur. </P>
+<P>See the section on <A HREF="#except">exceptions</A> for more details on the
+structure of the exception classes. </P>
+<P>I have defined a class Tracer that is intended to help locate the place
+where an error has occurred. At the beginning of a function I suggest you
+include a statement like </P>
+<PRE>   Tracer tr(&quot;name&quot;);
+</PRE>
+
+<P>where name is the name of the function. This name will be printed as part of
+the error message, if an exception occurs in that function, or in a function
+called from that function. You can change the name as you proceed through a
+function with the ReName function </P>
+<PRE>   tr.ReName(&quot;new name&quot;);
+</PRE>
+
+<P>if, for example, you want to track progress through the function. </P>
+<H2><A NAME="design"></A>5. Notes on the design of the
+library</H2>
+<P CLASS="small"><A HREF="#sue">next</A> - <A HREF="#top">skip</A> -
+<A HREF="#top">up</A> - <A HREF="#top">start</A></P>
+<TABLE WIDTH="100%">
+<TR>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A HREF="#sue">5.1
+Safety, usability, efficiency </A><BR>
+<A HREF="#mat_arr">5.2 Matrix vs array library </A><BR>
+<A HREF="#question">5.3 Design questions </A><BR>
+<A HREF="#stor">5.4 Data storage </A><BR>
+<A HREF="#mem_man">5.5 Memory management - 1 </A><BR>
+<A HREF="#mem_man2">5.6 Memory management - 2 </A><BR>
+<A HREF="#evalx">5.7 Evaluation of expressions </A></TD>
+<TD VALIGN="TOP" ALIGN="LEFT" WIDTH="50%"> <A
+HREF="#explode">5.8 Explosion in the number of operations </A><BR>
+<A HREF="#destr">5.9 Destruction of temporaries </A><BR>
+<A HREF="#calc">5.10 A calculus of matrix types </A><BR>
+<A HREF="#pointer">5.11 Pointer arithmetic </A><BR>
+<A HREF="#err_hand">5.12 Error handling </A><BR>
+<A HREF="#sparse">5.13 Sparse matrices </A><BR>
+<A HREF="#comp_mat">5.14 Complex matrices </A></TD>
+</TR>
+</TABLE>
+<P>I describe some of the ideas behind this package, some of the decisions that
+I needed to make and give some details about the way it works. You don't need
+to read this part of the documentation in order to use the package. </P>
+<P>It isn't obvious what is the best way of going about structuring a matrix
+package. I don't think you can figure this out with <I>thought</I> experiments.
+Different people have to try out different approaches. And someone else may
+have to figure out which is best. Or, more likely, the ultimate packages will
+lift some ideas from each of a variety of trial packages. So, I don't claim my
+package is an <I>ultimate</I> package, but simply a trial of a number of ideas.
+The following pages give some background on these ideas. </P>
+<H2><A NAME="sue"></A>5.1 Safety, usability,
+efficiency</H2>
+<P CLASS="small"><A HREF="#mat_arr">next</A> - <A HREF="#mat_arr">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A></P>
+<H3>Some general comments</H3>
+<P>A library like <I>newmat</I> needs to balance <I>safety</I>,
+<I>usability</I> and <I>efficiency</I>. </P>
+<P>By <B>safety</B>, I mean getting the right answer, and not causing crashes
+or damage to the computer system. </P>
+<P>By <B>usability</B>, I mean being easy to learn and use, including not being
+too complicated, being intuitive, saving the users' time, being nice to use. 
+</P>
+<P><B>Efficiency</B> means minimising the use of computer memory and time. </P>
+<P>In the early days of computers the emphasis was on efficiency. But computer
+power gets cheaper and cheaper, halving in price every 18 months. On the other
+hand the unaided human brain is probably not a lot better than it was 100,000
+years ago! So we should expect the balance to shift to put more emphasis on
+safety and usability and a little less on efficiency. So I don't mind if my
+programs are a little less efficient than programs written in pure C (or
+Fortran) if I gain substantially in safety and usability. But I would mind if
+they were a lot less efficient. </P>
+<H3>Type of use</H3>
+<P>Second reason for putting extra emphasis on safety and usability is the way
+I and, I suspect, most other users actually use <I>newmat</I>. Most completed
+programs are used only a few times. Some result is required for a client, paper
+or thesis. The program is developed and tested, the result is obtained, and the
+program archived. Of course bits of the program will be recycled for the next
+project. But it may be less usual for the same program to be run over and over
+again. So the cost, computer time + people time, is in the development time and
+often, much less in the actual time to run the final program. So good use of
+people time, especially during development is really important. This means you
+need highly usable libraries. </P>
+<P>So if you are dealing with matrices, you want the good interface that I have
+tried to provide in <I>newmat</I>, and, of course, reliable methods underneath
+it. </P>
+<P>Of course, efficiency is still important. We often want to run the biggest
+problem our computer will handle and often a little bigger. The C++ language
+almost lets us have both worlds. We can define a reasonably good interface, and
+get good efficiency in the use of the computer. </P>
+<H3>Levels of access</H3>
+<P>We can imagine the <I>black box</I> model of a <I>newmat</I>. Suppose the
+inside is hidden but can be accessed by the methods described in the
+<A HREF="#refer">reference</A> section. Then the interface is reasonably
+consistent and intuitive. Matrices can be accessed and manipulated in much the
+same way as doubles or ints in regular C. All accesses are checked. It is most
+unlikely that an incorrect index will crash the system. In general, users do
+not need to use pointers, so one shouldn't get pointers pointing into space.
+And, hopefully, you will get simpler code with less errors. </P>
+<P>There are some exceptions to this. In particular, the <A
+HREF="#elements">C-like subscripts</A> are not checked for validity. They give
+faster access but with a lower level of safety. </P>
+<P>Then there is the <a href="#scalar1">data()</a> function which takes you to
+the data array within a matrix. This takes you right inside the <I>black
+box</I>. But this is what you have to use if you are writing, for example, a
+new matrix factorisation, and require fast access to the data array. I have
+tried to write code to simplify access to the interior of a rectangular matrix,
+see file newmatrm.cpp, but I don't regard this as very successful, as yet, and
+have not included it in the documentation. Ideally we should have improved
+versions of this code for each of the major types of matrix. But, in reality,
+most of my matrix factorisations are written in what is basically the C
+language with very little C++. </P>
+<P>So our <I>box</I> is not very <I>black</I>. You have a choice of how far you
+penetrate. On the outside you have a good level of safety, but in some cases
+efficiency is compromised a little. If you penetrate inside the <I>box</I>
+safety is reduced but you can get better efficiency. </P>
+<H3>Some performance data</H3>
+<P>This section looks at the performance on <I>newmat</I> for simple sums,
+comparing it with C code and with a simple array program. 
+</P>
+<P>The following table lists the time (in seconds) for carrying out the
+operations <TT>X=A+B;</TT>, <TT>X=A+B+C;</TT>, <TT>X=A+B+C+D;</TT>, <TT>X=A+B+C+D+E;</TT> where
+<TT>X,A,B,C,D,E</TT> are of type ColumnVector, with a variety of programs. I am
+using Microsoft VC++, version 6 in  console mode under windows 2000 on a PC with 
+a 1 ghz Pentium III and 512 mbytes of memory. </P>
+<pre>    length    iters. newmat      C C-res.  subs.  array
+<b>X = A + B</b>
+         2   5000000   27.8    0.3    8.8    1.9    9.5 
+        20    500000    3.0    0.3    1.1    1.9    1.2 
+       200     50000    0.5    0.3    0.4    1.9    0.3 
+      2000      5000    0.4    0.3    0.4    2.0    1.0 
+     20000       500    4.5    4.5    4.5    6.7    4.4 
+    200000        50    5.2    4.7    5.5    5.8    5.2 
+
+<b>X = A + B + C</b>
+         2   5000000   36.6    0.4    8.9    2.5   12.2 
+        20    500000    4.0    0.4    1.2    2.5    1.6 
+       200     50000    0.8    0.3    0.5    2.5    0.5 
+      2000      5000    3.6    4.4    4.6    9.0    4.4 
+     20000       500    6.8    5.4    5.4    9.6    6.8 
+    200000        50    8.6    6.0    6.7    7.1    8.6 
+
+<b>X = A + B + C + D</b>
+         2   5000000   44.0    0.7    9.3    3.1   14.6 
+        20    500000    4.9    0.6    1.5    3.1    1.9 
+       200     50000    1.0    0.6    0.8    3.2    0.8 
+      2000      5000    5.6    6.6    6.8   11.5    5.9 
+     20000       500    9.0    6.7    6.8   11.0    8.5 
+    200000        50   11.9    7.1    7.9    9.5   12.0 
+
+<b>X = A + B + C + D + E</b>
+         2   5000000   50.6    1.0    9.5    3.8   17.1 
+        20    500000    5.7    0.8    1.7    3.9    2.4 
+       200     50000    1.3    0.9    1.0    3.9    1.0 
+      2000      5000    7.0    8.3    8.2   13.8    7.1 
+     20000       500   11.5    8.1    8.4   13.2   11.0 
+    200000        50   15.2    8.7    9.5   12.4   15.4 
+</pre>
+<P>I have <a target="_blank" href="add_time.png">graphed</a> the results 
+and included rather more array lengths.</P>
+
+<P>The first column gives the lengths of the arrays, the second the number of
+iterations and the remaining columns the total time required in seconds. If the
+only thing that consumed time was the double precision addition then the
+numbers within each block of the table would be the same. The summation is 
+repeated 5 times within each loop, for example:</P>
+<pre>   for (i=1; i&lt;=m; ++i)
+   {
+      X1 = A1+B1+C1; X2 = A2+B2+C2; X3 = A3+B3+C3;
+      X4 = A4+B4+C4; X5 = A5+B5+C5;
+   }</pre>
+<P>The column labelled <I>newmat</I> is using the standard <I>newmat</I> add. The column labelled <I>C</I> uses the usual C method: <TT>while
+(j1--) *x1++ = *a1++ + *b1++;</TT> . The following column also includes an
+<TT>X.ReSize()</TT> in the outer loop to correspond to the reassignment of
+memory that <I>newmat</I> would do. In the next column the calculation is using 
+the usual C style <I>for</I> loop
+and accessing the elements using <I>newmat</I> subscripts such as
+<TT>A(i)</TT>. The final column is the time taken by a
+simple array package. This uses an alternative method for avoiding temporaries 
+and unnecessary copies that does not involve runtime tests. It does its sums in blocks of 4 and copies in blocks of
+8 in the same way that <I>newmat</I> does. </P>
+<P>Here are my conclusions. </P>
+<UL>
+<LI><I>Newmat</I> does very badly for length 2 and doesn't do  well for
+length 20. There is  a lot of code in <I>newmat</I> for
+determining which sum algorithm to use and it is not surprising that this 
+impacts on performance for small lengths.
+However the <I>array</I> program is also having difficulty with length 2 so it
+is unlikely that the problem could be completely eliminated. </LI>
+<LI>For arrays of length 2000 or longer <I>newmat</I> is doing about as well as
+C and slightly better than C with resize in the <TT>X=A+B</TT> table. For the
+other two tables it tends to be slower, but not dramatically so. </LI>
+<LI>It is really important for fast processing with the Pentium III to stay 
+within the Pentium cache.</LI>
+<LI>Addition using the <I>newmat</I> subscripts, while considerably slower than
+the others, is still surprisingly good for the longer arrays. </LI>
+<LI>The <I>array</I> program and <I>newmat</I> are similar for
+lengths 2000 or higher (the longer times for the array program for the longest 
+arrays shown on the graph are probably a quirk of the timing program). </LI>
+</UL>
+<P>In summary: for the situation considered here, <I>newmat</I> is doing very
+well for large ColumnVectors, even for sums with several terms, but not so well
+for shorter ColumnVectors. </P>
+<H2><A NAME="mat_arr"></A>5.2 Matrix vs array
+library</H2>
+<P CLASS="small"><A HREF="#question">next</A> - <A HREF="#question">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>The <I>newmat</I> library is for the manipulation of matrices, including the
+standard operations such as multiplication as understood by numerical analysts,
+engineers and mathematicians. </P>
+<P>A matrix is a two dimensional array of numbers. However, very special
+operations such as matrix multiplication are defined specifically for matrices.
+This means that a <I>matrix</I> library, as I understand the term, is different
+from a general <I>array</I> library. Here are some contrasting properties.</P>
+<TABLE WIDTH="100%" BORDER="1">
+<TR>
+<TH VALIGN="TOP" WIDTH="20%" ALIGN="LEFT">Feature</TH>
+<TH VALIGN="TOP" WIDTH="40%" ALIGN="LEFT">Matrix
+library</TH>
+<TH VALIGN="TOP" WIDTH="40%" ALIGN="LEFT">Array
+library</TH>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Expressions</TD>
+<TD VALIGN="TOP" WIDTH="40%">Matrix expressions<TT>;</TT>
+<TT>*</TT> means matrix multiply; inverse function</TD>
+<TD VALIGN="TOP" WIDTH="40%">Arithmetic operations, if
+supported, mean elementwise combination of arrays</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Element access</TD>
+<TD VALIGN="TOP" WIDTH="40%">Access to the elements of a
+matrix</TD>
+<TD VALIGN="TOP" WIDTH="40%">High speed access to elements
+directly and perhaps with iterators</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Elementary functions</TD>
+<TD VALIGN="TOP" WIDTH="40%">For example: determinant,
+trace</TD>
+<TD VALIGN="TOP" WIDTH="40%">Matrix multiplication as a
+function</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Advanced functions</TD>
+<TD VALIGN="TOP" WIDTH="40%">For example: eigenvalue
+analysis</TD>
+<TD VALIGN="TOP" WIDTH="40%">&nbsp;</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Element types</TD>
+<TD VALIGN="TOP" WIDTH="40%">Real and possibly
+complex</TD>
+<TD VALIGN="TOP" WIDTH="40%">Wide range - real, integer, string
+etc</TD>
+</TR>
+<TR>
+<TD VALIGN="TOP" WIDTH="20%">Types</TD>
+<TD VALIGN="TOP" WIDTH="40%">Rectangular, symmetric, diagonal,
+etc</TD>
+<TD VALIGN="TOP" WIDTH="40%">One, two and three dimensional
+arrays, at least</TD>
+</TR>
+</TABLE>
+<P>Both types of library need to support access to sub-matrices or sub-arrays,
+have good efficiency and storage management, and graceful exit for errors. In
+both cases, we probably need two versions, one optimised for large matrices or
+arrays and one for small matrices or arrays.</P>
+<P>It may be possible to amalgamate the two sets of requirements to some
+extent. However <I>newmat</I> is definitely oriented towards the matrix library
+set.</P>
+<H2><A NAME="question"></A>5.3 Design questions</H2>
+<P CLASS="small"><A HREF="#stor">next</A> - <A HREF="#stor">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>Even within the bounds set by the requirements of a matrix library there is
+a substantial opportunity for variation between what different matrix packages
+might provide. It is not possible to build a matrix package that will meet
+everyone's requirements. In many cases if you put in one facility, you impose
+overheads on everyone using the package. This both in storage required for the
+program and in efficiency. Likewise a package that is optimised towards
+handling large matrices is likely to become less efficient for very small
+matrices where the administration time for the matrix may become significant
+compared with the time to carry out the operations. It is better to provide a
+variety of packages (hopefully compatible) so that most users can find one that
+meets their requirements. This package is intended to be one of these packages;
+but not all of them. </P>
+<P>Since my background is in statistical methods, this package is oriented
+towards the kinds things you need for statistical analyses. </P>
+<P>Now looking at some specific questions. </P>
+<H3>What size of matrices?</H3>
+<P>A matrix library may target small matrices (say 3 x 3), or medium sized
+matrices, or very large matrices. </P>
+<P>A library targeting very small matrices will seek to minimise
+administration. A library for medium sized or very large matrices can spend
+more time on administration in order to conserve space or optimise the
+evaluation of expressions. A library for very large matrices will need to pay
+special attention to storage and numerical properties. This library is designed
+for medium sized matrices. This means it is worth introducing some
+optimisations, but I don't have to worry about setting up some form of virtual
+memory. </P>
+<H3>Which matrix types?</H3>
+<P>As well as the usual rectangular matrices, matrices occurring repeatedly in
+numerical calculations are upper and lower triangular matrices, symmetric
+matrices and diagonal matrices. This is particularly the case in calculations
+involving least squares and eigenvalue calculations. So as a first stage these
+were the types I decided to include. </P>
+<P>It is also necessary to have types row vector and column vector. In a
+<I>matrix</I> package, in contrast to an <I>array</I> package, it is necessary
+to have both these types since they behave differently in matrix expressions.
+The vector types can be derived for the rectangular matrix type, so having them
+does not greatly increase the complexity of the package. </P>
+<P>The problem with having several matrix types is the number of versions of
+the binary operators one needs. If one has 5 distinct matrix types then a
+simple library will need 25 versions of each of the binary operators. In fact,
+we can evade this problem, but at the cost of some complexity. </P>
+<H3>What element types?</H3>
+<P>Ideally we would allow element types double, float, complex and int, at
+least. It might be reasonably easy, using templates or equivalent, to provide a
+library which could handle a variety of element types. However, as soon as one
+starts implementing the binary operators between matrices with different
+element types, again one gets an explosion in the number of operations one
+needs to consider. At the present time the compilers I deal with are not up to
+handling this problem with templates. (Of course, when I started writing
+<I>newmat</I> there were no templates). But even when the compilers do meet the
+specifications of the draft standard, writing a matrix package that allows for
+a variety of element types using the template mechanism is going to be very
+difficult. I am inclined to use templates in an <I>array</I> library but not in
+a <I>matrix</I> library. </P>
+<P>Hence I decided to implement only one element type. But the user can decide
+whether this is float or double. The package assumes elements are of type Real.
+The user typedefs Real to float or double. </P>
+<P>It might also be worth including symmetric and triangular matrices with
+extra precision elements (double or long double) to be used for storage only
+and with a minimum of operations defined. These would be used for accumulating
+the results of sums of squares and product matrices or multi-stage QR 
+decompositions. </P>
+<H3>Allow matrix expressions</H3>
+<P>I want to be able to write matrix expressions the way I would on paper. So
+if I want to multiply two matrices and then add the transpose of a third one I
+can write something like <TT>X = A * B + C.t();</TT>. I want this expression to
+be evaluated with close to the same efficiency as a hand-coded version. This is
+not so much of a problem with expressions including a multiply since the
+multiply will dominate the time. However, it is not so easy to achieve with
+expressions with just <TT>+</TT> and <TT>-</TT>. </P>
+<P>A second requirement is that temporary matrices generated during the
+evaluation of an expression are destroyed as quickly as possible. </P>
+<P>A desirable feature is that a certain amount of <I>intelligence</I> be
+displayed in the evaluation of an expression. For example, in the expression
+<TT>X = A.i() * B;</TT> where <TT>i()</TT> denotes inverse, it would be
+desirable if the inverse wasn't explicitly calculated. </P>
+<H3>Naming convention</H3>
+<P>How are classes and public member functions to be named? As a general rule I
+have spelt identifiers out in full with individual words being capitalised. For
+example <I>UpperTriangularMatrix</I>. If you don't like this you can #define or
+typedef shorter names. This convention means you can select an abbreviation
+scheme that makes sense to you. </P>
+<P>Exceptions to the general rule are the functions for transpose and inverse.
+To make matrix expressions more like the corresponding mathematical formulae, I
+have used the single letter abbreviations, <TT>t()</TT> and <TT>i()</TT>. </P>
+<H3>Row and column index ranges</H3>
+<P>In mathematical work matrix subscripts usually start at one. In C, array
+subscripts start at zero. In Fortran, they start at one. Possibilities for this
+package were to make them start at 0 or 1 or be arbitrary. </P>
+<P>Alternatively one could specify an <I>index set</I> for indexing the rows
+and columns of a matrix. One would be able to add or multiply matrices only if
+the appropriate row and column index sets were identical. </P>
+<P>In fact, I adopted the simpler convention of making the rows and columns of
+a matrix be indexed by an integer starting at one, following the traditional
+convention. In an earlier version of the package I had them starting at zero,
+but even I was getting mixed up when trying to use this earlier package. So I
+reverted to the more usual notation and started at 1. </P>
+<H3>Element access - method and checking</H3>
+<P>We want to be able to use the notation <TT>A(i,j)</TT> to specify the
+<TT>(i,j)</TT>-th element of a matrix. This is the way mathematicians expect to
+address the elements of matrices. I consider the notation <TT>A[i][j]</TT>
+totally alien. However I include this as an option to help people converting
+from C. </P>
+<P>There are two ways of working out the address of <TT>A(i,j)</TT>. One is
+using a <I>dope</I> vector which contains the first address of each row.
+Alternatively you can calculate the address using the formula appropriate for
+the structure of <TT>A</TT>. I use this second approach. It is probably slower,
+but saves worrying about an extra bit of storage. </P>
+<P>The other question is whether to check for <TT>i</TT> and <TT>j</TT> being
+in range. I do carry out this check following years of experience with both
+systems that do and systems that don't do this check. I would hope that the
+routines I supply with this package will reduce your need to access elements of
+matrices so speed of access is not a high priority. </P>
+<H3>Use iterators</H3>
+<P>Iterators are an alternative way of providing fast access to the elements of
+an array or matrix when they are to be accessed sequentially. They need to be
+customised for each type of matrix. I have not implemented iterators in this
+package, although some iterator like functions are used internally for some row
+and column functions. </P>
+<H2><A NAME="stor"></A>5.4 Data storage</H2>
+<P CLASS="small"><A HREF="#mem_man">next</A> - <A HREF="#mem_man">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<H3>The stack and heap</H3>
+<p>To understand how <i>newmat</i> stores matrices you need to know a little bit 
+about the <i>heap</i> and <i>stack</i>.</p>
+<p>The data values of variables or objects in a C++ program are stored in either 
+of two sections of memory called the <i>stack</i> and the <i>heap</i>. Sometimes 
+there is more than one <i>heap</i> to cater for different sized variables.</p>
+<p>If you declare an <i>automatic</i> variable</p>
+<pre>   int x;</pre>
+<p>then the value of <i>x</i> is stored on the <i>stack</i>. As you declare more 
+variables the stack gets bigger. When you exit a block (i.e a section of code 
+delimited by curly brackets <i>{...}</i>) the memory used by the automatic 
+variables declared in the block is released and the <i>stack</i> shrinks.</p>
+<p>When you declare a variable with <i>new</i>, for example,</p>
+<pre>   int* y = new int;</pre>
+<p>the pointer <i>y</i> is stored on the <i>stack</i> but the value it is 
+pointing to is stored on the <i>heap</i>. Memory on the <i>heap</i> is not 
+released until the program explicitly does this with a <i>delete</i> statement</p>
+<pre>   delete *y;</pre>
+<p>or the program exits.</p>
+<p>On the <i>stack</i>, variables and objects are is always added to the end of 
+the <i>stack</i> and are removed in the reverse order to that in which they are 
+added - that is the last on will be the first off. This is not the case with the <i>
+heap</i>, where the variables and objects can be removed in any order. So one 
+can get alternating pieces of used and unused memory. When a new variable or 
+object is declared on the <i>heap</i> the system needs to search for piece of 
+unused memory large enough to hold it. This means that storing on the <i>heap</i> 
+will usually be a slower process than storing on the <i>stack</i>. There is also 
+likely to be waste space on the <i>heap</i> because of gaps between the used 
+blocks of memory that are too small for the next object you want to store on the
+<i>heap</i>. There is also the possibility of wasting space if you forget to 
+remove a variable or object on the <i>heap</i> even though you have finished 
+using it. However, the <i>stack</i> is usually limited to holding small objects 
+with size known at compile time. Large objects, objects whose size you don't 
+know at compile time, and objects that you want to persist after the end of the 
+block need to be stored on the <i>heap</i>.</p>
+<p>In C++, the <i>constructor</i>/<i>destructor</i> system enables one to build 
+complicated objects such as matrices that behave as automatic variables stored 
+on the <i>stack</i>, so the programmer doesn't have to worry about deleting them 
+at the end of the block, but which really utilise the <i>heap</i> for storing 
+their data.</p>
+<H3>Structure of matrix objects</H3>
+<P>Each matrix object contains the basic information such as the number of rows
+and columns, the amount of memory used, a status variable and a pointer to the data array which is on
+the heap. So if you declare a matrix</P>
+<pre>   Matrix A(1000,1000);</pre>
+<p>there is an small amount of memory used on the stack for storing the numbers 
+of rows and columns, the amount of&nbsp; memory used, the status variable and 
+the pointer together with 1,000,000 <i>Real</i> locations stored on the heap. 
+When you exit the block in which <i>A</i> is declared, the heap memory used by
+<i>A</i> is automatically returned to the system, as well as the memory used on 
+the stack.</p>
+<p>Of course, if you use new to declare a matrix</p>
+<pre>   Matrix* B = new Matrix(1000,1000);</pre>
+<p>both the information about the size and the actual data are stored on heap 
+and not deleted until the program exits or you do an explicit delete:</p>
+<pre>   delete *B;</pre>
+<p>If you carry out an assignment with <tt>=</tt> or <tt>&lt;&lt;</tt> or do a 
+<tt>resize()</tt> the data array currently associated with a matrix is destroyed and 
+a new array generated. For example</p>
+<pre>   Matrix A(1000,1000);
+   Matrix B(50, 50);
+   ... put some values in B
+   A = B;</pre>
+<p>At the last step the heap memory associated with <i>A</i> is returned to the 
+system and a new block of heap memory is assigned to contain the new values. 
+This happens even if there is no change in the amount of memory required. </p>
+<H3>One block or several</H3>
+<P>The elements of the matrix are stored as a single array. Alternatives would
+have been to store each row as a separate array or a set of adjacent rows as a
+separate array. The present solution simplifies the program but limits the size
+of matrices in 16 bit PCs that have a 64k byte limit on the size of arrays (I
+don't use the <TT>huge</TT> keyword). The large arrays may also cause problems
+for memory management in smaller machines. [The 16 bit PC problem has largely
+gone away but it was a problem when much of <I>newmat</I> was written. Now,
+occasionally I run into the 32 bit PC problem.]</P>
+<H3>By row or by column or other</H3>
+<P>In Fortran two dimensional arrays are stored by column. In most other
+systems they are stored by row. I have followed this later convention. This
+makes it easier to interface with other packages written in C but harder to
+interface with those written in Fortran. This may have been a wrong decision.
+Most work on the efficient manipulation of large matrices is being done in
+Fortran. It would have been easier to use this work if I had adopted the
+Fortran convention. </P>
+<P>An alternative would be to store the elements by mid-sized rectangular
+blocks. This might impose less strain on memory management when one needs to
+access both rows and columns. </P>
+<H3>Storage of symmetric matrices</H3>
+<P>Symmetric matrices are stored as lower triangular matrices. The decision was
+pretty arbitrary, but it does slightly simplify the Cholesky decomposition
+program. </P>
+<H2><A NAME="mem_man"></A>5.5 Memory management -
+reference counting or status variable?</H2>
+<P CLASS="small"><A HREF="#mem_man2">next</A> - <A HREF="#mem_man2">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>Consider the instruction </P>
+<PRE>   X = A + B + C;
+</PRE>
+
+<P>To evaluate this a simple program will add <TT>A</TT> to <TT>B</TT> putting
+the total in a temporary <TT>T1</TT>. Then it will add <TT>T1</TT> to
+<TT>C</TT> creating another temporary <TT>T2</TT> which will be copied into
+<TT>X</TT>. <TT>T1</TT> and <TT>T2</TT> will sit around till the end of the
+execution of the statement and perhaps of the block. It would be faster if the
+program recognised that <TT>T1</TT> was temporary and stored the sum of
+<TT>T1</TT> and <TT>C</TT> back into <TT>T1</TT> instead of creating
+<TT>T2</TT> and then avoided the final copy by just assigning the contents of
+<TT>T1</TT> to <TT>X</TT> rather than copying. In this case there will be no
+temporaries requiring deletion. (More precisely there will be a header to be
+deleted but no contents). </P>
+<P>For an instruction like </P>
+<PRE>   X = (A * B) + (C * D);
+</PRE>
+
+<P>we can't easily avoid one temporary being left over, so we would like this
+temporary deleted as quickly as possible. </P>
+<P>I provide the functionality for doing all this by attaching a status
+variable to each matrix. This indicates if the matrix is temporary so that its
+memory is available for recycling or deleting. Any matrix operation checks the
+status variables of the matrices it is working with and recycles or deletes any
+temporary memory. </P>
+<P>An alternative or additional approach would be to use <I>reference counting
+and delayed copying</I> - also known as <I>copy on write</I>. If a program
+requests a matrix to be copied, the copy is delayed until an instruction is
+executed which modifies the memory of either the original matrix or the copy.
+If the original matrix is deleted before either matrix is modified, in effect,
+the values of the original matrix are transferred to the copy without any
+actual copying taking place. This solves the difficult problem of returning an
+object from a function without copying and saves the unnecessary copying in the
+previous examples. </P>
+<P>There are downsides to the delayed copying approach. Typically, for delayed
+copying one uses a structure like the following: </P>
+<PRE>   Matrix
+     |
+     +------&gt; Array Object
+     |          |
+     |          +------&gt; Data array
+     |          |
+     |          +------- Counter
+     |
+     +------ Dimension information
+
+</PRE>
+
+<P>where the arrows denote a pointer to a data structure. If one wants to
+access the <I>Data array</I> one will need to track through two pointers. If
+one is going to write, one will have to check whether one needs to copy first.
+This is not important when one is going to access the whole array, say, for a
+add operation. But if one wants to access just a single element, then it
+imposes a significant additional overhead on that operation. Any subscript
+operation would need to check whether an update was required - even read since
+it is hard for the compiler to tell whether a subscript access is a read or
+write. </P>
+<P>Some matrix libraries don't bother to do this. So if you write <TT>A =
+B;</TT> and then modify an element of one of <TT>A</TT> or <TT>B</TT>, then the
+same element of the other is also modified. I don't think this is acceptable
+behaviour. </P>
+<P>Delayed copy does not provide the additional functionality of my approach
+but I suppose it would be possible to have both delayed copy and tagging
+temporaries. </P>
+<P>My approach does not automatically avoid all copying. In particular, you
+need use a special technique to return a matrix from a function without
+copying. </P>
+<H2><A NAME="mem_man2"></A>5.6 Memory management -
+accessing contiguous locations</H2>
+<P CLASS="small"><A HREF="#evalx">next</A> - <A HREF="#evalx">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>Modern computers work faster if one accesses memory by running through
+contiguous locations rather than by jumping around all over the place. Newmat
+stores matrices <A HREF="#stor">by rows</A> so that algorithms that access
+memory by running along rows will tend to work faster than one that runs down
+columns. A number of the algorithms used in <i>Newmat</i> were developed before this
+was an issue and so are not as efficient as possible. </P>
+<P>I have gradually upgrading the algorithms to access memory by rows. The
+following table shows the current status of this process.</P>
+<TABLE WIDTH="100%" BORDER="1">
+<TR>
+<TH ALIGN="LEFT">Function</TH>
+<TH ALIGN="LEFT">Contiguous memory access</TH>
+<TH ALIGN="LEFT">Comment</TH>
+</TR>
+<TR>
+<TD>Add, subtract</TD>
+<TD>Yes</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Multiply</TD>
+<TD>Yes</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Concatenate</TD>
+<TD>Yes</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Transpose</TD>
+<TD>No</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Invert and solve</TD>
+<TD>Yes</TD>
+<TD>Mostly</TD>
+</TR>
+<TR>
+<TD>Cholesky</TD>
+<TD>Yes</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>QRZ, QRZT</TD>
+<TD>Yes</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>SVD</TD>
+<TD>No</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Jacobi</TD>
+<TD>No</TD>
+<TD>Not an issue; used only for smaller matrices</TD>
+</TR>
+<TR>
+<TD>Eigenvalues</TD>
+<TD>No</TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TD>Sort</TD>
+<TD>Yes</TD>
+<TD>Quick-sort is naturally good</TD>
+</TR>
+<TR>
+<TD>FFT</TD>
+<TD>?</TD>
+<TD>Could be improved?</TD>
+</TR>
+</TABLE>
+<p>This is now all rather out of date. With Pentiums, at least, the important 
+requirement for speed seems to be to minimise transfers between the RAM memory 
+and the on-chip memory. There isn't much you can do about add and subtract, but 
+there lots of possibilities for some of the other operations.</p>
+<H2><A NAME="evalx"></A>5.7 Evaluation of expressions -
+lazy evaluation</H2>
+<P CLASS="small"><A HREF="#explode">next</A> - <A HREF="#explode">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A></P>
+<P>Consider the instruction </P>
+<PRE>   X = B - X;
+</PRE>
+
+<P>A simple program will subtract <TT>X</TT> from <TT>B</TT>, store the result
+in a temporary <TT>T1</TT> and copy <TT>T1</TT> into <TT>X</TT>. It would be
+faster if the program recognised that the result could be stored directly into
+<TT>X</TT>. This would happen automatically if the program could look at the
+instruction first and mark <TT>X</TT> as temporary. </P>
+<P>C programmers would expect to avoid the same problem with </P>
+<PRE>   X = X - B;
+</PRE>
+
+<P>by using an operator <TT>-=</TT> </P>
+<PRE>   X -= B;
+</PRE>
+
+<P>However this is an unnatural notation for non C users and it may be nicer to
+write <TT>X = X - B</TT>; and know that the program will carry out the
+simplification. </P>
+<P>Another example where this intelligent analysis of an instruction is helpful
+is in </P>
+<PRE>   X = A.i() * B;
+</PRE>
+
+<P>where <TT>i()</TT> denotes inverse. Numerical analysts know it is
+inefficient to evaluate this expression by carrying out the inverse operation
+and then the multiply. Yet it is a convenient way of writing the instruction.
+It would be helpful if the program recognised this expression and carried out
+the more appropriate approach. </P>
+<P>I regard this interpretation of <TT>A.i() * B</TT> as just providing a
+convenient notation. The objective is not primarily to correct the errors of
+people who are unaware of the inefficiency of <TT>A.i() * B</TT> if interpreted
+literally. </P>
+<P>There is a third reason for the two-stage evaluation of expressions and this
+is probably the most important one. In C++ it is quite hard to return an
+expression from a function such as (<TT>*</TT>, <TT>+</TT> etc) without a copy.
+This is particularly the case when an assignment (<TT>=</TT>) is involved. The
+mechanism described here provides one way for avoiding this in matrix
+expressions. </P>
+<P>The C++ standard (section 12.8/15) allows the compiler to optimise away the
+copy when returning an object from a function (but there will still be one copy
+is an <span lang="en-nz">assignment </span>(=) is involved). This means special handling of returns from a
+function is less important when a modern optimising compiler is being
+used.&nbsp; </P>
+<P>To carry out this <I>intelligent</I> analysis of an instruction matrix
+expressions are evaluated in two stages. In the the first stage a tree
+representation of the expression is formed. For example <TT>(A+B)*C</TT> is
+represented by a tree </P>
+<PRE><TT>
+       *
+      / \
+     +   C
+    / \
+   A   B
+</TT></PRE>
+
+<P>Rather than adding <TT>A</TT> and <TT>B</TT> the <TT>+</TT> operator yields
+an object of a class <I>AddedMatrix</I> which is just a pair of pointers to
+<TT>A</TT> and <TT>B</TT>. Then the <TT>*</TT> operator yields a
+<I>MultipliedMatrix</I> which is a pair of pointers to the <I>AddedMatrix</I>
+and <TT>C</TT>. The tree is examined for any simplifications and then evaluated
+recursively. </P>
+<P>Further possibilities not yet included are to recognise <TT>A.t()*A</TT> and
+<TT>A.t()+A</TT> as symmetric or to improve the efficiency of evaluation of
+expressions like <TT>A+B+C</TT>, <TT>A*B*C</TT>, <TT>A*B.t()</TT> (<TT>t()</TT>
+denotes transpose). </P>
+<P>One of the disadvantages of the two-stage approach is that the types of
+matrix expressions are determined at run-time. So the compiler will not detect
+errors of the type </P>
+<PRE>   Matrix M;
+   DiagonalMatrix D;
+   ....;
+   D = M;
+</PRE>
+
+<P>We don't allow conversions using <TT>=</TT> when information would be lost.
+Such errors will be detected when the statement is executed. </P>
+<H2><A NAME="explode"></A>5.8 How to overcome an
+explosion in number of operations</H2>
+<P CLASS="small"><A HREF="#destr">next</A> - <A HREF="#destr">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>The package attempts to solve the problem of the large number of versions of
+the binary operations required when one has a variety of types. </P>
+<P>With <I>n</I> types of matrices the binary operations will each require
+<I>n</I>-squared separate algorithms. Some reduction in the number may be
+possible by carrying out conversions. However, the situation rapidly becomes
+impossible with more than 4 or 5 types. Doug Lea told me that it was possible
+to avoid this problem. I don't know what his solution is. Here's mine. </P>
+<P>Each matrix type includes routines for extracting individual rows or
+columns. I assume a row or column consists of a sequence of zeros, a sequence
+of stored values and then another sequence of zeros. Only a single algorithm is
+then required for each binary operation. The rows can be located very quickly
+since most of the matrices are stored row by row. Columns must be copied and so
+the access is somewhat slower. As far as possible my algorithms access the
+matrices by row. </P>
+<P>There is another approach. Each of the matrix types defined in this package
+can be set up so both rows and columns have their elements at equal intervals
+provided we are prepared to store the rows and columns in up to three chunks.
+With such an approach one could write a single &quot;generic&quot; algorithm
+for each of multiply and add. This would be a reasonable alternative to my
+approach. </P>
+<P>I provide several algorithms for operations like + . If one is adding two
+matrices of the same type then there is no need to access the individual rows
+or columns and a faster general algorithm is appropriate. </P>
+<P>Generally the method works well. However symmetric matrices are not always
+handled very efficiently (yet) since complete rows are not stored explicitly. 
+</P>
+<P>The original version of the package did not use this access by row or column
+method and provided the multitude of algorithms for the combination of
+different matrix types. The code file length turned out to be just a little
+longer than the present one when providing the same facilities with 5 distinct
+types of matrices. It would have been very difficult to increase the number of
+matrix types in the original version. Apparently 4 to 5 types is about the
+break even point for switching to the approach adopted in the present package. 
+</P>
+<P>However it must also be admitted that there is a substantial overhead in the
+approach adopted in the present package for small matrices. The test program
+developed for the original version of the package takes 30 to 50% longer to run
+with the current version (though there may be some other reasons for this).
+This is for matrices in the range 6x6 to 10x10. </P>
+<P>To try to improve the situation a little I do provide an ordinary matrix
+multiplication routine for the case when all the matrices involved are
+rectangular. </P>
+<H2><A NAME="destr"></A>5.9 Destruction of
+temporaries</H2>
+<P CLASS="small"><A HREF="#calc">next</A> - <A HREF="#calc">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>Versions before version 5 of newmat did not work correctly with Gnu C++
+(version 5 or earlier). This was because the tree structure used to represent a
+matrix expression was set up on the stack.&nbsp; Early versions of Gnu C++ destroyed temporary structures as soon as the
+function that accesses them finished.  To overcome this problem, there was an 
+option to store the temporaries forming the tree structure on the heap (created 
+with new) and to delete them explicitly. Now that the C++ standards committee 
+has said that temporary structures should not be destroyed before a statement 
+finishes, I have deleted this option.</P>
+<H2><A NAME="calc"></A>5.10 A calculus of matrix
+types</H2>
+<P CLASS="small"><A HREF="#pointer">next</A> - <A HREF="#pointer">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A></P>
+<P>The program needs to be able to work out the class of the result of a matrix
+expression. This is to check that a conversion is legal or to determine the
+class of an intermediate result. To assist with this, a class MatrixType is
+defined. Operators <TT>+</TT>, <TT>-</TT>, <TT>*</TT>, <TT>&gt;=</TT> are
+defined to calculate the types of the results of expressions or to check that
+conversions are legal. </P>
+<P>Early versions of <I>newmat</I> stored the types of the results of
+operations in a table. So, for example, if you multiplied an
+UpperTriangularMatrix by a LowerTriangularMatrix, <I>newmat</I> would look up
+the table and see that the result was of type Matrix. With this approach the
+<A HREF="#explode">exploding</A> number of operations problem recurred although
+not as seriously as when code had to be written for each pair of types. But
+there was always the suspicion that somewhere, there was an error in one of
+those 9x9 tables, that would be very hard to find. And the problem would get
+worse as additional matrix types or operators were included. </P>
+<P>The present version of <I>newmat</I> solves the problem by assigning
+<I>attributes</I> such as <I>diagonal</I> or <I>band</I> or <I>upper
+triangular</I> to each matrix type. Which attributes a matrix type has, is
+stored as bits in an integer. As an example, the DiagonalMatrix type has the
+bits corresponding to <I>diagonal</I>, <I>symmetric</I> and <I>band</I> equal
+to 1. By looking at the attributes of each of the operands of a binary
+operator, the program can work out the attributes of the result of the
+operation with simple bitwise operations. Hence it can deduce an appropriate
+type. The <I>symmetric</I> attribute is a minor problem because
+<I>symmetric</I> * <I>symmetric</I> does not yield <I>symmetric</I> unless both
+operands are <I>diagonal</I>. But otherwise very simple code can be used to
+deduce the attributes of the result of a binary operation. </P>
+<P>Tables of the types resulting from the binary operators are output at the
+beginning of the <A HREF="#testing">test</A> program. </P>
+<H2><A NAME="pointer"></A>5.11 Pointer arithmetic</H2>
+<P CLASS="small"><A HREF="#err_hand">next</A> - <A HREF="#err_hand">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>Suppose you do something like </P>
+<PRE>   int* y = new int[100];
+   y += 200;          // y points to something outside the array
+   // y is <B>never</B> accessed
+</PRE>
+
+<P>Then the standard says that the behaviour of the program is <I>undefined</I>
+even if <TT>y</TT> is never accessed. (You are allowed to calculate a pointer
+value one location beyond the end of the array). In practice, a program like
+this does not cause any problems with any compiler I have come across and
+no-one has reported any such problems to me. </P>
+<P>However, this <I>error</I> is detected by Borland's <I>Code Guard</I>
+bound's checker and this makes it very difficult to use this to use <I>Code
+Guard</I> to detect other problems since the output is swamped by reports of
+this <I>error</I>. </P>
+<P>Now consider </P>
+<PRE>   int* y = new int[100];
+   y += 200;          // y points to something outside the array
+   y -= 150;          // y points to something inside the array
+   // y <B>is</B> accessed
+</PRE>
+
+<P>Again this is not strictly correct but does not seem to cause a problem. But
+it is much more doubtful than the previous example. </P>
+<P>I removed most instances of the second version of the problem from Newmat09.
+Hopefully the remainder of these instances were removed from Newmat10. In addition, most instances of the first version of the
+problem have also been fixed. </P>
+<P>There is one exception. The interface to the <A HREF="#nric">Numerical
+Recipes in C</A> does still contain the second version of the problem. This is
+inevitable because of the way Numerical Recipes in C stores vectors and
+matrices. If you are running the <A HREF="#testing">test program</A> with a
+bounds checking program, edit <TT>tmt.h</TT> to disable the testing of the NRIC
+interface. </P>
+<P>The rule does does cause a problem for authors of matrix and
+multidimensional array packages. If we want to run down a column of a matrix we
+would like to do something like </P>
+<PRE>   // set values of column 1
+   Matrix A;
+   ... set dimensions and put values in A
+   Real* a = A.Store();               // points to first element
+   int nr = A.Nrows();                // number of rows
+   int nc = A.Ncols();                // number of columns
+   while (nr--)
+   {
+      *a = something to put in first element of row
+      a += nc;                        // jump to next element of column
+   }
+</PRE>
+
+<P>If the matrix has more than one column the last execution of <TT>a +=
+nc;</TT> will run off the end of the space allocated to the matrix and we'll
+get a bounds error report. </P>
+<P>Instead we have to use a program like </P>
+<PRE>   // set values of column 1
+   Matrix A;
+   ... set dimensions and put values in A
+   Real* a = A.Store();               // points to first element
+   int nr = A.Nrows();                // number of rows
+   int nc = A.Ncols();                // number of columns
+   if (nr != 0)
+   {
+      for(;;)
+      {
+         *a = something to put in first element of row
+         if (!(--nr)) break;
+         a += nc;                     // jump to next element of column
+      }
+   }
+</PRE>
+
+<P>which is more complicated and consequently introduces more chance of error. 
+</P>
+<H2><A NAME="err_hand"></A>5.12 Error handling 
+</H2>
+<P CLASS="small"><A HREF="#sparse">next</A> - <A HREF="#sparse">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>The library now does have a moderately graceful exit from errors. One can
+use either the simulated exceptions or the compiler supported exceptions. When
+newmat08 was released (in 1995), compiler exception handling in the compilers I
+had access to was unreliable. I recommended you used my simulated exceptions.
+In 1997 compiler supported exceptions  seemed to work on a variety of
+compilers - but not all compilers. This was still true in 2001. One compiler 
+company was still having problems in 2003 (not sure about 2004). Try using the
+compiler supported exceptions if you have a recent compiler, but if you are
+getting strange crashes or errors try going back to my simulated exceptions.</P>
+<P>The approach in the present library, attempting to simulate C++ exceptions,
+is not completely satisfactory, but seems a good interim solution for those who
+cannot use compiler supported exceptions. People who don't want exceptions in
+any shape or form, can set the option to exit the program if an exception is
+thrown. </P>
+<P>The exception mechanism cannot clean-up objects explicitly created by new.
+This must be explicitly carried out by the package writer or the package user.
+I have not yet done this completely with the present package so occasionally a
+little garbage may be left behind after an exception. I don't think this is a
+big problem, but it is one that needs fixing. </P>
+<H2><A NAME="sparse"></A>5.13 Sparse matrices</H2>
+<P CLASS="small"><A HREF="#comp_mat">next</A> - <A HREF="#comp_mat">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A></P>
+<P>The library does not support sparse matrices. </P>
+<P>For sparse matrices there is going to be some kind of structure vector. It
+is going to have to be calculated for the results of expressions in much the
+same way that types are calculated. In addition, a whole new set of row and
+column operations would have to be written. </P>
+<P>Sparse matrices are important for people solving large sets of differential
+equations as well as being important for statistical and operational research
+applications. </P>
+<P>But there are packages being developed specifically for sparse matrices and
+these might present the best approach, at least where sparse matrices are the
+main interest. </P>
+<H2><A NAME="comp_mat"></A>5.14 Complex matrices</H2>
+<P CLASS="small"><A HREF="#top">next</A> - <A HREF="#top">skip</A> -
+<A HREF="#design">up</A> - <A HREF="#top">start</A> </P>
+<P>The package does not yet support matrices with complex elements. There are
+at least two approaches to including these. One is to have matrices with
+complex elements. </P>
+<P>This probably means making new versions of the basic row and column
+operations for Real*Complex, Complex*Complex, Complex*Real and similarly for
+<TT>+</TT> and <TT>-</TT>. This would be OK, except that if I also want to do
+this for sparse matrices, then when you put these together, the whole thing
+will get out of hand. </P>
+<P>The alternative is to represent a Complex matrix by a pair of Real matrices.
+One probably needs another level of decoding expressions but I think it might
+still be simpler than the first approach. But there is going to be a problem
+with accessing elements and it does not seem possible to solve this in an
+entirely satisfactory way. </P>
+<P>Complex matrices are used extensively by electrical engineers and physicists
+and really should be fully supported in a comprehensive package. </P>
+<P>You can simulate most complex operations by representing <TT>Z = X + iY</TT>
+by </P>
+<PRE>    /  X   Y \
+    \ -Y   X / 
+</PRE>
+
+<P>Most matrix operations will simulate the corresponding complex operation,
+when applied to this matrix. But, of course, this matrix is essentially twice as big as you
+would need with a genuine complex matrix library.</P>
+<P CLASS="small"><A HREF="#top">return to top</A><BR>
+<A HREF="ol_doc.htm">return to online documentation page</A></P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+<P>&nbsp;</P>
+</BODY>
+</HTML>
\ No newline at end of file
Index: Shared/newmat/docs/rbd.css
===================================================================
RCS file: Shared/newmat/docs/rbd.css
diff -N Shared/newmat/docs/rbd.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/docs/rbd.css	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,19 @@
+/* Style sheet - if you are saving my files, please also save this file as rbd.css */
+h1           { font-family: Arial, Helvetica, sans-serif; font-size: 20pt; color: maroon }
+h2           { font-family: Arial, Helvetica, sans-serif; font-size: 16pt; color: maroon }
+h3           { font-family: Arial, Helvetica, sans-serif; font-size: 14pt; color: maroon }
+h4           { font-family: Arial, Helvetica, sans-serif; font-size: 12pt; color: maroon }
+body         { font-family: "Times New Roman", Times, serif; background-color: white }
+body.gray    { font-family: "Times New Roman", Times, serif; background-color: #CCCCCC }
+p            { font-family: "Times New Roman", Times, serif; margin-top: 8; margin-bottom: 8 }
+p.small      { font-family: "Times New Roman", Times, serif; font-size: 10pt; margin-top: 8; margin-bottom: 8 }
+ul           { line-height: 100%; margin-top: 2; margin-bottom: 2 }
+li           { margin-top: 2; margin-bottom: 2; font-size: 10pt }
+tt           { font-family: "Courier New", Courier, monospaced; font-size: 10pt }
+pre          { font-family: "Courier New", Courier, monospaced; font-size: 10pt }
+hr           { color: maroon }
+a:link       { color: blue }
+a:visited    { color: green }
+a:active     { color: red }
+table        { font-size: 10pt }
+.question    { color: navy; }
\ No newline at end of file
Index: Shared/newmat/docs/images/add_time.png
===================================================================
RCS file: Shared/newmat/docs/images/add_time.png
diff -N Shared/newmat/docs/images/add_time.png
Binary files /dev/null and /tmp/cvsJFYr1N differ
Index: Shared/newmat/extra/example.cpp
===================================================================
RCS file: Shared/newmat/extra/example.cpp
diff -N Shared/newmat/extra/example.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/example.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,336 @@
+//$$ example.cpp                             Example of use of matrix package
+
+#define WANT_STREAM                  // include.h will get stream fns
+#define WANT_MATH                    // include.h will get math fns
+                                     // newmatap.h will get include.h
+
+#include "newmatap.h"                // need matrix applications
+
+#include "newmatio.h"                // need matrix output routines
+
+#ifdef use_namespace
+using namespace NEWMAT;              // access NEWMAT namespace
+#endif
+
+
+// demonstration of matrix package on linear regression problem
+
+
+void test1(Real* y, Real* x1, Real* x2, int nobs, int npred)
+{
+   cout << "\n\nTest 1 - traditional, bad\n";
+
+   // traditional sum of squares and products method of calculation
+   // but not adjusting means; maybe subject to round-off error
+
+   // make matrix of predictor values with 1s into col 1 of matrix
+   int npred1 = npred+1;        // number of cols including col of ones.
+   Matrix X(nobs,npred1);
+   X.Column(1) = 1.0;
+
+   // load x1 and x2 into X
+   //    [use << rather than = when loading arrays]
+   X.Column(2) << x1;  X.Column(3) << x2;
+
+   // vector of Y values
+   ColumnVector Y(nobs); Y << y;
+
+   // form sum of squares and product matrix
+   //    [use << rather than = for copying Matrix into SymmetricMatrix]
+   SymmetricMatrix SSQ; SSQ << X.t() * X;
+
+   // calculate estimate
+   //    [bracket last two terms to force this multiplication first]
+   //    [ .i() means inverse, but inverse is not explicity calculated]
+   ColumnVector A = SSQ.i() * (X.t() * Y);
+
+   // Get variances of estimates from diagonal elements of inverse of SSQ
+   // get inverse of SSQ - we need it for finding D
+   DiagonalMatrix D; D << SSQ.i();
+   ColumnVector V = D.AsColumn();
+
+   // Calculate fitted values and residuals
+   ColumnVector Fitted = X * A;
+   ColumnVector Residual = Y - Fitted;
+   Real ResVar = Residual.SumSquare() / (nobs-npred1);
+
+   // Get diagonals of Hat matrix (an expensive way of doing this)
+   DiagonalMatrix Hat;  Hat << X * (X.t() * X).i() * X.t();
+
+   // print out answers
+   cout << "\nEstimates and their standard errors\n\n";
+
+   // make vector of standard errors
+   ColumnVector SE(npred1);
+   for (int i=1; i<=npred1; i++) SE(i) = sqrt(V(i)*ResVar);
+   // use concatenation function to form matrix and use matrix print
+   // to get two columns
+   cout << setw(11) << setprecision(5) << (A | SE) << endl;
+
+   cout << "\nObservations, fitted value, residual value, hat value\n";
+
+   // use concatenation again; select only columns 2 to 3 of X
+   cout << setw(9) << setprecision(3) <<
+     (X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn());
+   cout << "\n\n";
+}
+
+void test2(Real* y, Real* x1, Real* x2, int nobs, int npred)
+{
+   cout << "\n\nTest 2 - traditional, OK\n";
+
+   // traditional sum of squares and products method of calculation
+   // with subtraction of means - less subject to round-off error
+   // than test1
+
+   // make matrix of predictor values
+   Matrix X(nobs,npred);
+
+   // load x1 and x2 into X
+   //    [use << rather than = when loading arrays]
+   X.Column(1) << x1;  X.Column(2) << x2;
+
+   // vector of Y values
+   ColumnVector Y(nobs); Y << y;
+
+   // make vector of 1s
+   ColumnVector Ones(nobs); Ones = 1.0;
+
+   // calculate means (averages) of x1 and x2 [ .t() takes transpose]
+   RowVector M = Ones.t() * X / nobs;
+
+   // and subtract means from x1 and x1
+   Matrix XC(nobs,npred);
+   XC = X - Ones * M;
+
+   // do the same to Y [use Sum to get sum of elements]
+   ColumnVector YC(nobs);
+   Real m = Sum(Y) / nobs;  YC = Y - Ones * m;
+
+   // form sum of squares and product matrix
+   //    [use << rather than = for copying Matrix into SymmetricMatrix]
+   SymmetricMatrix SSQ; SSQ << XC.t() * XC;
+
+   // calculate estimate
+   //    [bracket last two terms to force this multiplication first]
+   //    [ .i() means inverse, but inverse is not explicity calculated]
+   ColumnVector A = SSQ.i() * (XC.t() * YC);
+
+   // calculate estimate of constant term
+   //    [AsScalar converts 1x1 matrix to Real]
+   Real a = m - (M * A).AsScalar();
+
+   // Get variances of estimates from diagonal elements of inverse of SSQ
+   //    [ we are taking inverse of SSQ - we need it for finding D ]
+   Matrix ISSQ = SSQ.i(); DiagonalMatrix D; D << ISSQ;
+   ColumnVector V = D.AsColumn();
+   Real v = 1.0/nobs + (M * ISSQ * M.t()).AsScalar();
+					    // for calc variance of const
+
+   // Calculate fitted values and residuals
+   int npred1 = npred+1;
+   ColumnVector Fitted = X * A + a;
+   ColumnVector Residual = Y - Fitted;
+   Real ResVar = Residual.SumSquare() / (nobs-npred1);
+
+   // Get diagonals of Hat matrix (an expensive way of doing this)
+   Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X;
+   DiagonalMatrix Hat;  Hat << X1 * (X1.t() * X1).i() * X1.t();
+
+   // print out answers
+   cout << "\nEstimates and their standard errors\n\n";
+   cout.setf(ios::fixed, ios::floatfield);
+   cout << setw(11) << setprecision(5)  << a << " ";
+   cout << setw(11) << setprecision(5)  << sqrt(v*ResVar) << endl;
+   // make vector of standard errors
+   ColumnVector SE(npred);
+   for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar);
+   // use concatenation function to form matrix and use matrix print
+   // to get two columns
+   cout << setw(11) << setprecision(5) << (A | SE) << endl;
+   cout << "\nObservations, fitted value, residual value, hat value\n";
+   cout << setw(9) << setprecision(3) <<
+     (X | Y | Fitted | Residual | Hat.AsColumn());
+   cout << "\n\n";
+}
+
+void test3(Real* y, Real* x1, Real* x2, int nobs, int npred)
+{
+   cout << "\n\nTest 3 - Cholesky\n";
+
+   // traditional sum of squares and products method of calculation
+   // with subtraction of means - using Cholesky decomposition
+
+   Matrix X(nobs,npred);
+   X.Column(1) << x1;  X.Column(2) << x2;
+   ColumnVector Y(nobs); Y << y;
+   ColumnVector Ones(nobs); Ones = 1.0;
+   RowVector M = Ones.t() * X / nobs;
+   Matrix XC(nobs,npred);
+   XC = X - Ones * M;
+   ColumnVector YC(nobs);
+   Real m = Sum(Y) / nobs;  YC = Y - Ones * m;
+   SymmetricMatrix SSQ; SSQ << XC.t() * XC;
+
+   // Cholesky decomposition of SSQ
+   LowerTriangularMatrix L = Cholesky(SSQ);
+
+   // calculate estimate
+   ColumnVector A = L.t().i() * (L.i() * (XC.t() * YC));
+
+   // calculate estimate of constant term
+   Real a = m - (M * A).AsScalar();
+
+   // Get variances of estimates from diagonal elements of invoice of SSQ
+   DiagonalMatrix D; D << L.t().i() * L.i();
+   ColumnVector V = D.AsColumn();
+   Real v = 1.0/nobs + (L.i() * M.t()).SumSquare();
+
+   // Calculate fitted values and residuals
+   int npred1 = npred+1;
+   ColumnVector Fitted = X * A + a;
+   ColumnVector Residual = Y - Fitted;
+   Real ResVar = Residual.SumSquare() / (nobs-npred1);
+
+   // Get diagonals of Hat matrix (an expensive way of doing this)
+   Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X;
+   DiagonalMatrix Hat;  Hat << X1 * (X1.t() * X1).i() * X1.t();
+
+   // print out answers
+   cout << "\nEstimates and their standard errors\n\n";
+   cout.setf(ios::fixed, ios::floatfield);
+   cout << setw(11) << setprecision(5)  << a << " ";
+   cout << setw(11) << setprecision(5)  << sqrt(v*ResVar) << endl;
+   ColumnVector SE(npred);
+   for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar);
+   cout << setw(11) << setprecision(5) << (A | SE) << endl;
+   cout << "\nObservations, fitted value, residual value, hat value\n";
+   cout << setw(9) << setprecision(3) <<
+      (X | Y | Fitted | Residual | Hat.AsColumn());
+   cout << "\n\n";
+}
+
+void test4(Real* y, Real* x1, Real* x2, int nobs, int npred)
+{
+   cout << "\n\nTest 4 - QR triangularisation\n";
+
+   // QR triangularisation method
+ 
+   // load data - 1s into col 1 of matrix
+   int npred1 = npred+1;
+   Matrix X(nobs,npred1); ColumnVector Y(nobs);
+   X.Column(1) = 1.0;  X.Column(2) << x1;  X.Column(3) << x2;  Y << y;
+
+   // do Householder triangularisation
+   // no need to deal with constant term separately
+   Matrix X1 = X;                 // Want copy of matrix
+   ColumnVector Y1 = Y;
+   UpperTriangularMatrix U; ColumnVector M;
+   QRZ(X1, U); QRZ(X1, Y1, M);    // Y1 now contains resids
+   ColumnVector A = U.i() * M;
+   ColumnVector Fitted = X * A;
+   Real ResVar = Y1.SumSquare() / (nobs-npred1);
+
+   // get variances of estimates
+   U = U.i(); DiagonalMatrix D; D << U * U.t();
+
+   // Get diagonals of Hat matrix
+   DiagonalMatrix Hat;  Hat << X1 * X1.t();
+
+   // print out answers
+   cout << "\nEstimates and their standard errors\n\n";
+   ColumnVector SE(npred1);
+   for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar);
+   cout << setw(11) << setprecision(5) << (A | SE) << endl;
+   cout << "\nObservations, fitted value, residual value, hat value\n";
+   cout << setw(9) << setprecision(3) << 
+      (X.Columns(2,3) | Y | Fitted | Y1 | Hat.AsColumn());
+   cout << "\n\n";
+}
+
+void test5(Real* y, Real* x1, Real* x2, int nobs, int npred)
+{
+   cout << "\n\nTest 5 - singular value\n";
+
+   // Singular value decomposition method
+ 
+   // load data - 1s into col 1 of matrix
+   int npred1 = npred+1;
+   Matrix X(nobs,npred1); ColumnVector Y(nobs);
+   X.Column(1) = 1.0;  X.Column(2) << x1;  X.Column(3) << x2;  Y << y;
+
+   // do SVD
+   Matrix U, V; DiagonalMatrix D;
+   SVD(X,D,U,V);                              // X = U * D * V.t()
+   ColumnVector Fitted = U.t() * Y;
+   ColumnVector A = V * ( D.i() * Fitted );
+   Fitted = U * Fitted;
+   ColumnVector Residual = Y - Fitted;
+   Real ResVar = Residual.SumSquare() / (nobs-npred1);
+
+   // get variances of estimates
+   D << V * (D * D).i() * V.t();
+
+   // Get diagonals of Hat matrix
+   DiagonalMatrix Hat;  Hat << U * U.t();
+
+   // print out answers
+   cout << "\nEstimates and their standard errors\n\n";
+   ColumnVector SE(npred1);
+   for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar);
+   cout << setw(11) << setprecision(5) << (A | SE) << endl;
+   cout << "\nObservations, fitted value, residual value, hat value\n";
+   cout << setw(9) << setprecision(3) << 
+      (X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn());
+   cout << "\n\n";
+}
+
+int main()
+{
+   cout << "\nDemonstration of Matrix package\n";
+   cout << "\nPrint a real number (may help lost memory test): " << 3.14159265 << "\n";
+
+   // Test for any memory not deallocated after running this program
+   Real* s1; { ColumnVector A(8000); s1 = A.Store(); }
+
+   {
+      // the data
+
+      Real y[]  = { 8.3, 5.5, 8.0, 8.5, 5.7, 4.4, 6.3, 7.9, 9.1 };
+      Real x1[] = { 2.4, 1.8, 2.4, 3.0, 2.0, 1.2, 2.0, 2.7, 3.6 };
+      Real x2[] = { 1.7, 0.9, 1.6, 1.9, 0.5, 0.6, 1.1, 1.0, 0.5 };
+
+
+      int nobs = 9;                           // number of observations
+      int npred = 2;                          // number of predictor values
+
+      // we want to find the values of a,a1,a2 to give the best
+      // fit of y[i] with a0 + a1*x1[i] + a2*x2[i]
+      // Also print diagonal elements of hat matrix, X*(X.t()*X).i()*X.t()
+
+      // this example demonstrates five methods of calculation
+
+      Try
+      {
+         test1(y, x1, x2, nobs, npred);
+         test2(y, x1, x2, nobs, npred);
+         test3(y, x1, x2, nobs, npred);
+         test4(y, x1, x2, nobs, npred);
+         test5(y, x1, x2, nobs, npred);
+      }
+      CatchAll { cout << BaseException::what(); }
+   }
+
+#ifdef DO_FREE_CHECK
+   FreeCheck::Status();
+#endif
+   Real* s2; { ColumnVector A(8000); s2 = A.Store(); }
+   cout << "\n\nThe following test does not work with all compilers - see documentation\n";
+   cout << "Checking for lost memory: "
+      << (unsigned long)s1 << " " << (unsigned long)s2 << " ";
+   if (s1 != s2) cout << " - error\n"; else cout << " - ok\n";
+
+   return 0;
+
+}
+
Index: Shared/newmat/extra/example.txt
===================================================================
RCS file: Shared/newmat/extra/example.txt
diff -N Shared/newmat/extra/example.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/example.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,123 @@
+
+Demonstration of Matrix package
+
+Print a real number (may help lost memory test): 3.14159
+
+
+Test 1 - traditional, bad
+
+Estimates and their standard errors
+
+    1.39166     0.53188 
+    1.98310     0.20932 
+    0.95221     0.27731 
+
+
+Observations, fitted value, residual value, hat value
+    2.400     1.700     8.300     7.770     0.530     0.280 
+    1.800     0.900     5.500     5.818    -0.318     0.190 
+    2.400     1.600     8.000     7.675     0.325     0.229 
+    3.000     1.900     8.500     9.150    -0.650     0.446 
+    2.000     0.500     5.700     5.834    -0.134     0.271 
+    1.200     0.600     4.400     4.343     0.057     0.480 
+    2.000     1.100     6.300     6.405    -0.105     0.143 
+    2.700     1.000     7.900     7.698     0.202     0.153 
+    3.600     0.500     9.100     9.007     0.093     0.808 
+
+
+
+
+Test 2 - traditional, OK
+
+Estimates and their standard errors
+
+    1.39166     0.53188
+    1.98310     0.20932 
+    0.95221     0.27731 
+
+
+Observations, fitted value, residual value, hat value
+    2.400     1.700     8.300     7.770     0.530     0.280 
+    1.800     0.900     5.500     5.818    -0.318     0.190 
+    2.400     1.600     8.000     7.675     0.325     0.229 
+    3.000     1.900     8.500     9.150    -0.650     0.446 
+    2.000     0.500     5.700     5.834    -0.134     0.271 
+    1.200     0.600     4.400     4.343     0.057     0.480 
+    2.000     1.100     6.300     6.405    -0.105     0.143 
+    2.700     1.000     7.900     7.698     0.202     0.153 
+    3.600     0.500     9.100     9.007     0.093     0.808 
+
+
+
+
+Test 3 - Cholesky
+
+Estimates and their standard errors
+
+    1.39166     0.53188
+    1.98310     0.20932 
+    0.95221     0.27731 
+
+
+Observations, fitted value, residual value, hat value
+    2.400     1.700     8.300     7.770     0.530     0.280 
+    1.800     0.900     5.500     5.818    -0.318     0.190 
+    2.400     1.600     8.000     7.675     0.325     0.229 
+    3.000     1.900     8.500     9.150    -0.650     0.446 
+    2.000     0.500     5.700     5.834    -0.134     0.271 
+    1.200     0.600     4.400     4.343     0.057     0.480 
+    2.000     1.100     6.300     6.405    -0.105     0.143 
+    2.700     1.000     7.900     7.698     0.202     0.153 
+    3.600     0.500     9.100     9.007     0.093     0.808 
+
+
+
+
+Test 4 - QR triangularisation
+
+Estimates and their standard errors
+
+    1.39166     0.53188 
+    1.98310     0.20932 
+    0.95221     0.27731 
+
+
+Observations, fitted value, residual value, hat value
+    2.400     1.700     8.300     7.770     0.530     0.280 
+    1.800     0.900     5.500     5.818    -0.318     0.190 
+    2.400     1.600     8.000     7.675     0.325     0.229 
+    3.000     1.900     8.500     9.150    -0.650     0.446 
+    2.000     0.500     5.700     5.834    -0.134     0.271 
+    1.200     0.600     4.400     4.343     0.057     0.480 
+    2.000     1.100     6.300     6.405    -0.105     0.143 
+    2.700     1.000     7.900     7.698     0.202     0.153 
+    3.600     0.500     9.100     9.007     0.093     0.808 
+
+
+
+
+Test 5 - singular value
+
+Estimates and their standard errors
+
+    1.39166     0.53188 
+    1.98310     0.20932 
+    0.95221     0.27731 
+
+
+Observations, fitted value, residual value, hat value
+    2.400     1.700     8.300     7.770     0.530     0.280 
+    1.800     0.900     5.500     5.818    -0.318     0.190 
+    2.400     1.600     8.000     7.675     0.325     0.229 
+    3.000     1.900     8.500     9.150    -0.650     0.446 
+    2.000     0.500     5.700     5.834    -0.134     0.271 
+    1.200     0.600     4.400     4.343     0.057     0.480 
+    2.000     1.100     6.300     6.405    -0.105     0.143 
+    2.700     1.000     7.900     7.698     0.202     0.153 
+    3.600     0.500     9.100     9.007     0.093     0.808 
+
+
+
+
+The following test does not work with all compilers - see documentation
+Checking for lost memory: 8206652 8206652  - ok
Index: Shared/newmat/extra/garch.cpp
===================================================================
RCS file: Shared/newmat/extra/garch.cpp
diff -N Shared/newmat/extra/garch.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/garch.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,175 @@
+
+#define WANT_STREAM
+#define WANT_MATH
+#define WANT_FSTREAM
+
+#include "newmatap.h"
+#include "newmatio.h"
+#include "newmatnl.h"
+
+#ifdef use_namespace
+using namespace RBD_LIBRARIES;
+#endif
+
+// This is a demonstration of a special case of the Garch model
+// Observe two series X and Y of length n
+// and suppose
+//    Y(i) = beta * X(i) + epsilon(i)
+// where epsilon(i) is normally distributed with zero mean and variance =
+//    h(i) = alpha0 + alpha1 * square(epsilon(i-1)) + beta1 * h(i-1).
+// Then this program is supposed to estimate beta, alpha0, alpha1, beta1
+// The Garch model is supposed to model something like an instability
+// in the stock or options market following an unexpected result.
+// alpha1 determines the size of the instability and beta1 determines how
+// quickly is dies away.
+// We should, at least, have an X of several columns and beta as a vector
+
+inline Real square(Real x) { return x*x; }
+
+// the class that defines the GARCH log-likelihood
+
+class GARCH11_LL : public LL_D_FI
+{
+   ColumnVector Y;                 // Y values
+   ColumnVector X;                 // X values
+   ColumnVector D;                 // derivatives of loglikelihood
+   SymmetricMatrix D2;             // - approximate second derivatives
+   int n;                          // number of observations
+   Real beta, alpha0, alpha1, beta1;
+                                   // the parameters
+
+public:
+
+   GARCH11_LL(const ColumnVector& y, const ColumnVector& x)
+      : Y(y), X(x), n(y.Nrows()) {}
+                                   // constructor - load Y and X values
+
+   void Set(const ColumnVector& p) // set parameter values
+   {
+      para = p;
+      beta = para(1); alpha0 = para(2);
+      alpha1 = para(3); beta1 = para(4);
+   }
+
+   bool IsValid();                 // are parameters valid
+   Real LogLikelihood();           // return the loglikelihood
+   ReturnMatrix Derivatives();     // derivatives of log-likelihood
+   ReturnMatrix FI();              // Fisher Information matrix
+};
+
+bool GARCH11_LL::IsValid()
+{ return alpha0>0 && alpha1>0 && beta1>0 && (alpha1+beta1)<1.0; }
+
+Real GARCH11_LL::LogLikelihood()
+{
+//   cout << endl << "                           ";
+//   cout << setw(10) << setprecision(5) << beta;
+//   cout << setw(10) << setprecision(5) << alpha0;
+//   cout << setw(10) << setprecision(5) << alpha1;
+//   cout << setw(10) << setprecision(5) << beta1;
+//   cout << endl;
+   ColumnVector H(n);              // residual variances
+   ColumnVector U = Y - X * beta;  // the residuals
+   ColumnVector LH(n);     // derivative of log-likelihood wrt H
+			   // each row corresponds to one observation
+   LH(1)=0;
+   Matrix Hderiv(n,4);     // rectangular matrix of derivatives
+			   // of H wrt parameters
+			   // each row corresponds to one observation
+			   // each column to one of the parameters
+
+   // Regard Y(1) as fixed and don't include in likelihood
+   // then put in an expected value of H(1) in place of actual value
+   //   which we don't know. Use
+   // E{H(i)} = alpha0 + alpha1 * E{square(epsilon(i-1))} + beta1 * E{H(i-1)}
+   // and  E{square(epsilon(i-1))} = E{H(i-1)} = E{H(i)}
+   Real denom = (1-alpha1-beta1);
+   H(1) = alpha0/denom;    // the expected value of H
+   Hderiv(1,1) = 0;
+   Hderiv(1,2) = 1.0 / denom;
+   Hderiv(1,3) = alpha0 / square(denom);
+   Hderiv(1,4) = Hderiv(1,3);
+   Real LL = 0.0;          // the log likelihood
+   Real sum1 = 0;          // for forming derivative wrt beta
+   Real sum2 = 0;          // for forming second derivative wrt beta
+   for (int i=2; i<=n; i++)
+   {
+      Real u1 = U(i-1); Real h1 = H(i-1);
+      Real h = alpha0 + alpha1*square(u1) + beta1*h1; // variance of this obsv.
+      H(i) = h; Real u = U(i);
+      LL += log(h) + square(u) / h;        // -2 * log likelihood
+      // Hderiv are derivatives of h with respect to the parameters
+      // need to allow for h1 depending on parameters
+      Hderiv(i,1) = -2*u1*alpha1*X(i-1) + beta1*Hderiv(i-1,1);  // beta
+      Hderiv(i,2) = 1 + beta1*Hderiv(i-1,2);                    // alpha0
+      Hderiv(i,3) = square(u1) + beta1*Hderiv(i-1,3);           // alpha1
+      Hderiv(i,4) = h1 + beta1*Hderiv(i-1,4);                   // beta1
+      LH(i) = -0.5 * (1/h - square(u/h));
+      sum1 += u * X(i)/ h;
+      sum2 += square(X(i)) / h;
+   }
+   D = Hderiv.t()*LH;         // derivatives of likelihood wrt parameters
+   D(1) += sum1;              // add on deriv wrt beta from square(u) term
+//   cout << setw(10) << setprecision(5) << D << endl;
+
+   // do minus expected value of second derivatives
+   if (wg)                    // do only if second derivatives wanted
+   {
+      Hderiv.Row(1) = 0.0;
+      Hderiv = H.AsDiagonal().i() * Hderiv;
+      D2 << Hderiv.t() * Hderiv;  D2 = D2 / 2.0;
+      D2(1,1) += sum2;
+//      cout << setw(10) << setprecision(5) << D2 << endl;
+//      DiagonalMatrix DX; EigenValues(D2,DX);
+//      cout << setw(10) << setprecision(5) << DX << endl;
+
+   }
+   return -0.5 * LL;
+}
+
+ReturnMatrix GARCH11_LL::Derivatives()
+{ return D; }
+
+ReturnMatrix GARCH11_LL::FI()
+{
+   if (!wg) cout << endl << "unexpected call of FI" << endl;
+   return D2;
+}
+
+
+
+int main()
+{
+   // get data
+   ifstream fin("garch.dat");
+   if (!fin) { cout << "cannot find garch.dat\n"; exit(1); }
+   int n; fin >> n;            // series length
+   // Y contains the dependant variable, X the predictor variable
+   ColumnVector Y(n), X(n);
+   int i;
+   for (i=1; i<=n; i++) fin >> Y(i) >> X(i);
+   cout << "Read " << n << " data points - begin fit\n\n";
+   // now do the fit
+   ColumnVector H(n);
+   GARCH11_LL garch11(Y,X);                  // loglikehood "object"
+   MLE_D_FI mle_d_fi(garch11,100,0.0001);    // mle "object"
+   ColumnVector Para(4);                     // to hold the parameters
+   Para << 0.0 << 0.1 << 0.1 << 0.1;         // starting values
+      // (Should change starting values to a more intelligent formula)
+   mle_d_fi.Fit(Para);                       // do the fit
+   ColumnVector SE;
+   mle_d_fi.GetStandardErrors(SE);
+   cout << "\n\n";
+   cout << "estimates and standard errors\n";
+   cout << setw(15) << setprecision(5) << (Para | SE) << endl << endl;
+   SymmetricMatrix Corr;
+   mle_d_fi.GetCorrelations(Corr);
+   cout << "correlation matrix\n";
+   cout << setw(10) << setprecision(2) << Corr << endl << endl;
+   cout << "inverse of correlation matrix\n";
+   cout << setw(10) << setprecision(2) << Corr.i() << endl << endl;
+   return 0;
+}
+
+
+
Index: Shared/newmat/extra/garch.dat
===================================================================
RCS file: Shared/newmat/extra/garch.dat
diff -N Shared/newmat/extra/garch.dat
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/garch.dat	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,502 @@
+500
+   3.44443   -0.49800 
+   1.43549   -0.49600 
+   3.70477   -0.49400 
+  -3.82558   -0.49200 
+   1.20130   -0.49000 
+  -2.62383   -0.48800 
+  -1.34321   -0.48600 
+  -0.35801   -0.48400 
+  -2.18813   -0.48200 
+  -1.98628   -0.48000 
+  -1.53262   -0.47800 
+  -1.45007   -0.47600 
+  -1.18593   -0.47400 
+  -0.55274   -0.47200 
+  -1.55943   -0.47000 
+  -3.10084   -0.46800 
+   0.44254   -0.46600 
+  -0.63936   -0.46400 
+   2.44989   -0.46200 
+  -2.14392   -0.46000 
+   0.47310   -0.45800 
+  -1.64464   -0.45600 
+   0.56628   -0.45400 
+  -0.80925   -0.45200 
+  -0.78961   -0.45000 
+  -1.12984   -0.44800 
+  -0.50715   -0.44600 
+  -1.75134   -0.44400 
+  -1.04231   -0.44200 
+   0.94435   -0.44000 
+   1.16306   -0.43800 
+  -2.87888   -0.43600 
+  -3.31084   -0.43400 
+  -3.06191   -0.43200 
+   1.06977   -0.43000 
+   3.50462   -0.42800 
+   3.94848   -0.42600 
+   1.56565   -0.42400 
+  -5.21742   -0.42200 
+   1.94652   -0.42000 
+  -3.01182   -0.41800 
+  -3.88963   -0.41600 
+  -0.31319   -0.41400 
+  -5.71752   -0.41200 
+  -6.72218   -0.41000 
+   3.23482   -0.40800 
+   2.12675   -0.40600 
+  -0.10975   -0.40400 
+  -1.73790   -0.40200 
+  -0.86870   -0.40000 
+  -1.46022   -0.39800 
+  -0.22960   -0.39600 
+   0.01596   -0.39400 
+   0.00568   -0.39200 
+  -3.41221   -0.39000 
+  -0.47401   -0.38800 
+  -1.76305   -0.38600 
+  -0.49640   -0.38400 
+  -2.36184   -0.38200 
+  -0.09625   -0.38000 
+  -2.81448   -0.37800 
+   3.14301   -0.37600 
+   1.88025   -0.37400 
+  -2.61618   -0.37200 
+  -1.56239   -0.37000 
+   0.95722   -0.36800 
+   1.29773   -0.36600 
+  -1.45155   -0.36400 
+  -0.63342   -0.36200 
+  -0.78925   -0.36000 
+   0.42473   -0.35800 
+   1.39599   -0.35600 
+   1.03934   -0.35400 
+  -0.11042   -0.35200 
+   0.89123   -0.35000 
+   0.93411   -0.34800 
+   2.78027   -0.34600 
+   3.37402   -0.34400 
+  -0.07986   -0.34200 
+   0.79142   -0.34000 
+  -4.17148   -0.33800 
+  -1.26717   -0.33600 
+  -4.36262   -0.33400 
+   1.17431   -0.33200 
+  -1.75656   -0.33000 
+   0.40495   -0.32800 
+   0.17572   -0.32600 
+  -0.27991   -0.32400 
+  -0.85524   -0.32200 
+  -1.23380   -0.32000 
+  -1.01889   -0.31800 
+   1.08393   -0.31600 
+  -0.55989   -0.31400 
+  -1.91643   -0.31200 
+  -1.23897   -0.31000 
+  -0.85407   -0.30800 
+   0.35218   -0.30600 
+  -1.57057   -0.30400 
+   0.20665   -0.30200 
+   0.19680   -0.30000 
+   0.03116   -0.29800 
+   0.09100   -0.29600 
+   1.03416   -0.29400 
+  -0.16048   -0.29200 
+  -0.27530   -0.29000 
+  -0.11056   -0.28800 
+  -2.11332   -0.28600 
+  -0.51348   -0.28400 
+  -0.16360   -0.28200 
+   1.30712   -0.28000 
+  -0.94392   -0.27800 
+  -0.06838   -0.27600 
+  -0.04095   -0.27400 
+  -2.00364   -0.27200 
+   0.63950   -0.27000 
+  -1.02895   -0.26800 
+  -0.17454   -0.26600 
+  -0.86659   -0.26400 
+   0.81698   -0.26200 
+   0.51579   -0.26000 
+  -0.74525   -0.25800 
+   2.43378   -0.25600 
+   0.89364   -0.25400 
+   1.81727   -0.25200 
+  -0.29667   -0.25000 
+  -0.99628   -0.24800 
+   0.09452   -0.24600 
+   1.73730   -0.24400 
+   0.36819   -0.24200 
+  -1.56521   -0.24000 
+   0.74916   -0.23800 
+   0.56802   -0.23600 
+  -1.34157   -0.23400 
+  -0.65638   -0.23200 
+  -2.12183   -0.23000 
+  -2.35486   -0.22800 
+  -2.09369   -0.22600 
+  -3.30745   -0.22400 
+  -4.14763   -0.22200 
+  -3.56306   -0.22000 
+   0.78907   -0.21800 
+  -3.74014   -0.21600 
+  -2.73770   -0.21400 
+  -4.43153   -0.21200 
+  -0.80243   -0.21000 
+  -0.17474   -0.20800 
+  -0.38250   -0.20600 
+  -0.98962   -0.20400 
+  -1.41965   -0.20200 
+   0.90585   -0.20000 
+   0.66850   -0.19800 
+  -0.81629   -0.19600 
+  -3.04422   -0.19400 
+  -0.94514   -0.19200 
+   0.05209   -0.19000 
+   0.21315   -0.18800 
+  -0.86960   -0.18600 
+  -1.72978   -0.18400 
+  -2.85623   -0.18200 
+  -3.15650   -0.18000 
+  -0.09176   -0.17800 
+  -1.27376   -0.17600 
+  -1.06533   -0.17400 
+   1.21766   -0.17200 
+   0.41706   -0.17000 
+  -0.30885   -0.16800 
+   0.78344   -0.16600 
+  -1.76348   -0.16400 
+   2.46496   -0.16200 
+  -0.32712   -0.16000 
+   1.38586   -0.15800 
+   0.33513   -0.15600 
+   0.66116   -0.15400 
+   0.92420   -0.15200 
+  -0.67200   -0.15000 
+  -0.90707   -0.14800 
+  -0.41053   -0.14600 
+   0.62288   -0.14400 
+   0.78497   -0.14200 
+   0.99670   -0.14000 
+  -2.19972   -0.13800 
+   0.21922   -0.13600 
+  -0.15003   -0.13400 
+  -0.72706   -0.13200 
+   0.13596   -0.13000 
+  -0.00235   -0.12800 
+   0.50025   -0.12600 
+   0.80875   -0.12400 
+  -0.71010   -0.12200 
+  -3.85477   -0.12000 
+   2.45549   -0.11800 
+  -2.87772   -0.11600 
+   1.03987   -0.11400 
+  -1.41914   -0.11200 
+  -1.87414   -0.11000 
+   1.32656   -0.10800 
+   2.15281   -0.10600 
+   3.25624   -0.10400 
+  -3.72420   -0.10200 
+  -4.01675   -0.10000 
+   1.19241   -0.09800 
+   0.35189   -0.09600 
+  -0.40223   -0.09400 
+   0.84146   -0.09200 
+   1.08746   -0.09000 
+   2.20874   -0.08800 
+  -0.18822   -0.08600 
+  -1.29757   -0.08400 
+  -1.36022   -0.08200 
+   0.54575   -0.08000 
+  -0.23008   -0.07800 
+   0.00750   -0.07600 
+   1.81600   -0.07400 
+  -0.07319   -0.07200 
+   0.70587   -0.07000 
+  -2.67033   -0.06800 
+   0.67446   -0.06600 
+  -0.21002   -0.06400 
+   2.11396   -0.06200 
+  -0.94189   -0.06000 
+   0.27803   -0.05800 
+  -0.92172   -0.05600 
+   1.37776   -0.05400 
+   2.72565   -0.05200 
+   0.47208   -0.05000 
+  -3.33845   -0.04800 
+  -0.20695   -0.04600 
+  -2.18905   -0.04400 
+  -4.33413   -0.04200 
+   0.17860   -0.04000 
+  -5.57817   -0.03800 
+  -0.32771   -0.03600 
+   1.47321   -0.03400 
+   2.33767   -0.03200 
+   1.22282   -0.03000 
+  -1.48593   -0.02800 
+   0.79435   -0.02600 
+   0.54491   -0.02400 
+   1.31706   -0.02200 
+  -1.26472   -0.02000 
+  -1.72634   -0.01800 
+  -3.85299   -0.01600 
+   0.43717   -0.01400 
+  -3.39362   -0.01200 
+  -3.60823   -0.01000 
+   0.18868   -0.00800 
+   1.23035   -0.00600 
+   1.70454   -0.00400 
+  -1.44766   -0.00200 
+   0.99808    0.00000 
+   0.24554    0.00200 
+   1.44446    0.00400 
+   0.96697    0.00600 
+  -3.30396    0.00800 
+  -5.97223    0.01000 
+   1.22379    0.01200 
+   6.00662    0.01400 
+   4.43380    0.01600 
+   2.01081    0.01800 
+  -2.74552    0.02000 
+   1.19452    0.02200 
+   3.81020    0.02400 
+   2.04597    0.02600 
+   0.66764    0.02800 
+   2.68350    0.03000 
+  -2.85514    0.03200 
+   0.21727    0.03400 
+   1.88780    0.03600 
+   2.23549    0.03800 
+   1.57589    0.04000 
+   1.92344    0.04200 
+  -1.78414    0.04400 
+  -0.67367    0.04600 
+   0.19357    0.04800 
+   1.00246    0.05000 
+   2.13782    0.05200 
+   1.90734    0.05400 
+   0.43943    0.05600 
+  -0.55699    0.05800 
+   1.76985    0.06000 
+  -0.77310    0.06200 
+  -0.33812    0.06400 
+  -0.85572    0.06600 
+  -2.49390    0.06800 
+  -3.17954    0.07000 
+   2.86688    0.07200 
+   2.03589    0.07400 
+  -1.34393    0.07600 
+   1.01839    0.07800 
+  -0.15220    0.08000 
+   1.17978    0.08200 
+   1.96847    0.08400 
+   1.90596    0.08600 
+   3.72675    0.08800 
+  -0.65513    0.09000 
+  -1.45672    0.09200 
+  -0.08779    0.09400 
+  -0.39105    0.09600 
+   1.88645    0.09800 
+   2.34710    0.10000 
+  -2.65900    0.10200 
+  -0.47996    0.10400 
+  -2.51512    0.10600 
+  -3.59097    0.10800 
+  -1.62117    0.11000 
+  -2.43947    0.11200 
+   3.50339    0.11400 
+   3.05144    0.11600 
+  -2.73565    0.11800 
+  -1.31556    0.12000 
+   1.85250    0.12200 
+  -1.03864    0.12400 
+   0.79097    0.12600 
+  -0.12426    0.12800 
+   0.48964    0.13000 
+   1.42419    0.13200 
+   0.55098    0.13400 
+  -0.78121    0.13600 
+  -0.01716    0.13800 
+  -1.27952    0.14000 
+   1.91981    0.14200 
+   0.25822    0.14400 
+   0.68516    0.14600 
+   1.25616    0.14800 
+  -1.40178    0.15000 
+  -0.99551    0.15200 
+   1.45728    0.15400 
+  -1.66513    0.15600 
+  -1.20284    0.15800 
+   1.84775    0.16000 
+  -1.91535    0.16200 
+   0.34142    0.16400 
+   1.90641    0.16600 
+   1.55524    0.16800 
+   1.77263    0.17000 
+   1.25731    0.17200 
+  -0.66331    0.17400 
+   0.93506    0.17600 
+   0.87120    0.17800 
+   0.73840    0.18000 
+  -1.48181    0.18200 
+  -1.76043    0.18400 
+   0.96176    0.18600 
+   1.29128    0.18800 
+   1.20889    0.19000 
+   0.78386    0.19200 
+   1.54668    0.19400 
+  -0.25996    0.19600 
+   0.93201    0.19800 
+   1.30374    0.20000 
+   2.23175    0.20200 
+  -0.42525    0.20400 
+   1.12784    0.20600 
+  -0.42014    0.20800 
+  -0.00577    0.21000 
+  -1.14837    0.21200 
+   2.48454    0.21400 
+  -0.51466    0.21600 
+  -0.06257    0.21800 
+  -1.25993    0.22000 
+   1.26623    0.22200 
+   3.05099    0.22400 
+  -1.84077    0.22600 
+  -0.36058    0.22800 
+   2.65788    0.23000 
+  -0.17717    0.23200 
+   1.68915    0.23400 
+  -1.53406    0.23600 
+   1.78097    0.23800 
+  -1.24217    0.24000 
+  -4.17466    0.24200 
+   0.80433    0.24400 
+   0.70856    0.24600 
+  -0.96881    0.24800 
+   0.87322    0.25000 
+  -2.45936    0.25200 
+   2.95677    0.25400 
+   1.81628    0.25600 
+  -0.85793    0.25800 
+   1.02089    0.26000 
+  -1.05425    0.26200 
+  -0.29861    0.26400 
+   1.69682    0.26600 
+   1.07389    0.26800 
+   0.22183    0.27000 
+   1.72766    0.27200 
+  -0.99746    0.27400 
+  -2.14178    0.27600 
+  -1.67924    0.27800 
+   1.56520    0.28000 
+  -0.86864    0.28200 
+   2.65155    0.28400 
+  -2.27166    0.28600 
+   0.68310    0.28800 
+   0.84102    0.29000 
+   0.64604    0.29200 
+   0.68712    0.29400 
+   1.56297    0.29600 
+  -0.68136    0.29800 
+   1.25519    0.30000 
+  -1.38612    0.30200 
+   2.36320    0.30400 
+   5.40128    0.30600 
+  -1.14776    0.30800 
+  -1.36081    0.31000 
+   0.07679    0.31200 
+  -0.17231    0.31400 
+   1.19094    0.31600 
+   0.09285    0.31800 
+  -0.85191    0.32000 
+  -0.43739    0.32200 
+  -0.22950    0.32400 
+   2.21298    0.32600 
+   0.75045    0.32800 
+   0.97489    0.33000 
+  -0.62158    0.33200 
+   1.10503    0.33400 
+   0.36977    0.33600 
+  -0.32894    0.33800 
+   2.13729    0.34000 
+   4.42019    0.34200 
+  -2.80916    0.34400 
+   2.28181    0.34600 
+   2.59053    0.34800 
+  -1.52891    0.35000 
+  -1.35202    0.35200 
+   1.27639    0.35400 
+   0.28782    0.35600 
+   0.83540    0.35800 
+  -0.32867    0.36000 
+   1.16891    0.36200 
+   0.02511    0.36400 
+  -0.71878    0.36600 
+   0.69811    0.36800 
+   1.29399    0.37000 
+   0.86300    0.37200 
+  -0.12139    0.37400 
+  -0.28069    0.37600 
+   3.07623    0.37800 
+  -2.91737    0.38000 
+   0.16709    0.38200 
+  -1.60815    0.38400 
+   0.02795    0.38600 
+   1.19657    0.38800 
+   0.04390    0.39000 
+   0.95983    0.39200 
+  -1.83683    0.39400 
+  -1.69167    0.39600 
+   3.15836    0.39800 
+   2.24002    0.40000 
+   0.45225    0.40200 
+   1.35014    0.40400 
+  -1.67177    0.40600 
+  -0.97317    0.40800 
+   4.20922    0.41000 
+  -0.03983    0.41200 
+  -0.35933    0.41400 
+  -1.49772    0.41600 
+   2.72900    0.41800 
+  -2.61061    0.42000 
+  -0.26581    0.42200 
+  -4.30162    0.42400 
+  -3.55225    0.42600 
+  -5.60739    0.42800 
+   2.26730    0.43000 
+  -0.05568    0.43200 
+  -0.14348    0.43400 
+  -1.73015    0.43600 
+  -1.01649    0.43800 
+  -2.39568    0.44000 
+   3.41626    0.44200 
+   2.23817    0.44400 
+  -1.02668    0.44600 
+   3.18086    0.44800 
+   0.71908    0.45000 
+  -0.37826    0.45200 
+  -0.39837    0.45400 
+   0.50378    0.45600 
+   0.38287    0.45800 
+   2.95404    0.46000 
+  -1.16143    0.46200 
+   0.89913    0.46400 
+  -0.82190    0.46600 
+   1.30638    0.46800 
+   0.89138    0.47000 
+   0.85038    0.47200 
+  -1.38925    0.47400 
+   3.74026    0.47600 
+   4.60999    0.47800 
+   1.31364    0.48000 
+   5.17183    0.48200 
+   1.82162    0.48400 
+   1.09830    0.48600 
+   1.36666    0.48800 
+  -0.09676    0.49000 
+   0.74155    0.49200 
+   1.21910    0.49400 
+   1.20746    0.49600 
+   0.82236    0.49800 
+   1.54856    0.50000 
+
Index: Shared/newmat/extra/garch.txt
===================================================================
RCS file: Shared/newmat/extra/garch.txt
diff -N Shared/newmat/extra/garch.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/garch.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,45 @@
+Read 500 data points - begin fit
+
+
+        -2247.993783            25945.58733
+        -537.4533239
+        -554.5885614
+        -537.2164816            26.36266449
+        -520.7034774
+        -519.7069034            6.153112127
+        -516.7045383
+         -516.690955            1.394658892
+         -516.396412
+         -516.215149           0.1555724069
+        -516.1509657
+        -516.1486772          0.02342168856
+        -516.1420803
+        -516.1404735         0.002342030975
+        -516.1395282
+        -516.1394913        0.0003287516503
+        -516.1393961
+        -516.1393755         3.25631984e-05
+Converged
+
+
+estimates and standard errors
+        1.56690         0.22311 
+        0.80046         0.20274 
+        0.45307         0.08428 
+        0.34655         0.09081 
+
+
+correlation matrix
+      1.00       0.00      -0.02       0.01 
+      0.00       1.00       0.21      -0.81 
+     -0.02       0.21       1.00      -0.63 
+      0.01      -0.81      -0.63       1.00 
+
+
+inverse of correlation matrix
+      1.00       0.03       0.04       0.04 
+      0.03       4.77       2.28       5.28 
+      0.04       2.28       2.73       3.55 
+      0.04       5.28       3.55       7.48 
+
+
Index: Shared/newmat/extra/newmat.lfl
===================================================================
RCS file: Shared/newmat/extra/newmat.lfl
diff -N Shared/newmat/extra/newmat.lfl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/newmat.lfl	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,4 @@
+newmat.h
+newmatap.h
+newmatio.h
+myexcept.cpp
Index: Shared/newmat/extra/nl_ex.cpp
===================================================================
RCS file: Shared/newmat/extra/nl_ex.cpp
diff -N Shared/newmat/extra/nl_ex.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nl_ex.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,93 @@
+// This is an example of a non-linear least squares fit. The example
+// is from "Nonlinear estimation" by Gavin Ross (Springer,1990), p 63.
+// There are better ways of doing the fit in this case so this
+// example is just an example.
+
+// The model is E(y) = a + b exp(-kx) and there are 6 data points.
+
+#define WANT_STREAM
+#define WANT_MATH
+#include "newmatnl.h"
+#include "newmatio.h"
+
+#ifdef use_namespace
+using namespace RBD_LIBRARIES;
+#endif
+
+
+// first define the class describing the predictor function
+
+class Model_3pe : public R1_Col_I_D
+{
+   ColumnVector x_values;         // the values of "x"
+   RowVector deriv;               // values of derivatives
+public:
+   Model_3pe(const ColumnVector& X_Values)
+      : x_values(X_Values) { deriv.ReSize(3); }
+											 // load X data
+   Real operator()(int);
+   bool IsValid() { return para(3)>0; }
+                                  // require "k" > 0
+   ReturnMatrix Derivatives() { return deriv; }
+};
+
+Real Model_3pe::operator()(int i)
+{
+   Real a = para(1); Real b = para(2); Real k = para(3);
+   Real xvi = x_values(i);
+   Real e = exp(-k * xvi);
+   deriv(1) = 1.0;                    // calculate derivatives
+   deriv(2) = e;
+   deriv(3) = - b * e * xvi;
+   return a + b * e;                  // function value
+}
+
+int main()
+{
+   {
+      // Get the data
+      ColumnVector X(6);
+      ColumnVector Y(6);
+      X << 1   << 2   <<  3   <<  4   <<  6   <<  8;
+      Y << 3.2 << 7.9 << 11.1 << 14.5 << 16.7 << 18.3;
+
+
+      // Do the fit
+      Model_3pe model(X);                // the model object
+      NonLinearLeastSquares NLLS(model); // the non-linear least squares
+                                         // object
+      ColumnVector Para(3);              // for the parameters
+      Para << 9 << -6 << .5;             // trial values of parameters
+      cout << "Fitting parameters\n";
+      NLLS.Fit(Y,Para);                  // do the fit
+
+      // Inspect the results
+      ColumnVector SE;                   // for the standard errors
+      NLLS.GetStandardErrors(SE);
+      cout << "\n\nEstimates and standard errors\n" <<
+         setw(10) << setprecision(2) << (Para | SE) << endl;
+      Real ResidualSD = sqrt(NLLS.ResidualVariance());
+      cout << "\nResidual s.d. = " << setw(10) << setprecision(2) <<
+         ResidualSD << endl;
+      SymmetricMatrix Correlations;
+      NLLS.GetCorrelations(Correlations);
+      cout << "\nCorrelationMatrix\n" <<
+         setw(10) << setprecision(2) << Correlations << endl;
+      ColumnVector Residuals;
+      NLLS.GetResiduals(Residuals);
+      DiagonalMatrix Hat;
+      NLLS.GetHatDiagonal(Hat);
+      cout << "\nX, Y, Residual, Hat\n" << setw(10) << setprecision(2) <<
+         (X | Y | Residuals | Hat.AsColumn()) << endl;
+      // recover var/cov matrix
+      SymmetricMatrix D;
+      D << SE.AsDiagonal() * Correlations * SE.AsDiagonal();
+      cout << "\nVar/cov\n" << setw(14) << setprecision(4) << D << endl;
+   }
+
+#ifdef DO_FREE_CHECK
+   FreeCheck::Status();
+#endif
+ 
+   return 0;
+}
Index: Shared/newmat/extra/nl_ex.txt
===================================================================
RCS file: Shared/newmat/extra/nl_ex.txt
diff -N Shared/newmat/extra/nl_ex.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nl_ex.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,42 @@
+Fitting parameters
+
+               70.02918529     209.6252324 0.1541078372
+               94.78295699
+               49.23360397     147.1803571 0.1734849298
+               1.848950128
+               0.7422941575      1.70673579 0.1733822274
+               0.2113527145
+               0.1955923541   0.06041118379 0.1754552928
+               0.1754553498
+               0.1754553471 2.341694142e-08 0.1754553393
+Converged
+
+
+Estimates and standard errors
+     19.77       0.73 
+    -23.63       0.82 
+      0.35       0.04 
+
+
+Residual s.d. =       0.42
+
+CorrelationMatrix
+      1.00      -0.05      -0.91 
+     -0.05       1.00      -0.31 
+     -0.91      -0.31       1.00 
+
+
+X, Y, Residual, Hat
+      1.00       3.20       0.10       0.89 
+      2.00       7.90      -0.11       0.33 
+      3.00      11.10      -0.38       0.39 
+      4.00      14.50       0.58       0.35 
+      6.00      16.70      -0.16       0.32 
+      8.00      18.30      -0.02       0.73 
+
+
+Var/cov
+        0.5295        -0.0324        -0.0250 
+       -0.0324         0.6668        -0.0096 
+       -0.0250        -0.0096         0.0014 
+
Index: Shared/newmat/extra/nm_b55.mak
===================================================================
RCS file: Shared/newmat/extra/nm_b55.mak
diff -N Shared/newmat/extra/nm_b55.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_b55.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,193 @@
+BORLANDPATH = "C:\program files\Borland\cbuilder5"
+
+TASM = TASM32
+TLIB = tlib
+TLINK = ilink32
+LIBPATH = $(BORLANDPATH)\LIB
+INCLUDEPATH = $(BORLANDPATH)\INCLUDE
+
+DIFF = sdiff
+PRE =
+
+CC = bcc32 -W- -v- -H- -3 -N -Og -Oi -Ov -f -I$(INCLUDEPATH)
+
+.cpp.obj:
+   $(CC) -c {$< }
+
+everything:    	tmt.exe example.exe test_exc.exe nl_ex.exe sl_ex.exe garch.exe 
+
+newmat_lobj = newmat1.obj newmat2.obj newmat3.obj newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj newmatex.obj bandmat.obj submat.obj myexcept.obj cholesky.obj evalue.obj fft.obj hholder.obj jacobi.obj newfft.obj sort.obj svd.obj newmatrm.obj newmat9.obj
+
+newmat.lib:    	$(newmat_lobj)
+   $(TLIB) $@ /P32 /u $(newmat_lobj)
+
+tmt_obj = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj tmtm.obj
+
+tmt.exe:       	$(tmt_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(tmt_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+example_obj = example.obj
+
+example.exe:   	$(example_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(example_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+test_exc_obj = test_exc.obj
+
+test_exc.exe:  	$(test_exc_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(test_exc_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+nl_ex_obj = nl_ex.obj newmatnl.obj
+
+nl_ex.exe:     	$(nl_ex_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(nl_ex_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+sl_ex_obj = sl_ex.obj solution.obj myexcept.obj
+
+sl_ex.exe:     	$(sl_ex_obj)
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(sl_ex_obj),$@,,import32.lib cw32.lib
+|
+
+garch_obj = garch.obj newmatnl.obj
+
+garch.exe:     	$(garch_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(garch_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+newmat1.obj:   	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.obj:   	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.obj:   	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.obj:   	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.obj:   	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.obj:   	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.obj:   	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.obj:   	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.obj:  	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.obj:   	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.obj:    	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.obj:  	myexcept.cpp include.h myexcept.h
+
+cholesky.obj:  	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.obj:    	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.obj:       	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.obj:   	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.obj:    	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.obj:    	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.obj:      	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.obj:       	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.obj:  	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.obj:   	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.obj:       	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.obj:      	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.obj:      	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.obj:      	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.obj:      	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.obj:      	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.obj:      	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.obj:      	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.obj:      	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.obj:      	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.obj:      	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.obj:      	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.obj:      	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.obj:      	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.obj:      	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.obj:      	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.obj:      	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.obj:      	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.obj:      	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.obj:      	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.obj:      	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.obj:      	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.obj:      	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.obj:   	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.obj:  	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.obj:     	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.obj:  	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.obj:     	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.obj:  	solution.cpp include.h myexcept.h solution.h
+
+garch.obj:     	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt.exe
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example.exe
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc.exe
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex.exe
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex.exe
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch.exe
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_b56.mak
===================================================================
RCS file: Shared/newmat/extra/nm_b56.mak
diff -N Shared/newmat/extra/nm_b56.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_b56.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,193 @@
+BORLANDPATH = "C:\program files\Borland\cbuilder6"
+
+TASM = TASM32
+TLIB = tlib
+TLINK = ilink32
+LIBPATH = $(BORLANDPATH)\LIB
+INCLUDEPATH = $(BORLANDPATH)\INCLUDE
+
+DIFF = sdiff
+PRE =
+
+CC = bcc32 -W- -v- -H- -6 -Og -Oi -Ov -I$(INCLUDEPATH)
+
+.cpp.obj:
+   $(CC) -c {$< }
+
+everything:    	tmt.exe example.exe test_exc.exe nl_ex.exe sl_ex.exe garch.exe 
+
+newmat_lobj = newmat1.obj newmat2.obj newmat3.obj newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj newmatex.obj bandmat.obj submat.obj myexcept.obj cholesky.obj evalue.obj fft.obj hholder.obj jacobi.obj newfft.obj sort.obj svd.obj newmatrm.obj newmat9.obj
+
+newmat.lib:    	$(newmat_lobj)
+   $(TLIB) $@ /P32 /u $(newmat_lobj)
+
+tmt_obj = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj tmtm.obj
+
+tmt.exe:       	$(tmt_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(tmt_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+example_obj = example.obj
+
+example.exe:   	$(example_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(example_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+test_exc_obj = test_exc.obj
+
+test_exc.exe:  	$(test_exc_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(test_exc_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+nl_ex_obj = nl_ex.obj newmatnl.obj
+
+nl_ex.exe:     	$(nl_ex_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(nl_ex_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+sl_ex_obj = sl_ex.obj solution.obj myexcept.obj
+
+sl_ex.exe:     	$(sl_ex_obj)
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(sl_ex_obj),$@,,import32.lib cw32.lib
+|
+
+garch_obj = garch.obj newmatnl.obj
+
+garch.exe:     	$(garch_obj) newmat.lib
+   $(TLINK) /x/L$(LIBPATH)/Gn -Tpe -ap -c @&&|
+c0x32.obj $(garch_obj),$@,, newmat.lib import32.lib cw32.lib
+|
+
+newmat1.obj:   	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.obj:   	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.obj:   	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.obj:   	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.obj:   	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.obj:   	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.obj:   	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.obj:   	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.obj:  	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.obj:   	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.obj:    	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.obj:  	myexcept.cpp include.h myexcept.h
+
+cholesky.obj:  	cholesky.cpp include.h newmat.h newmatrm.h myexcept.h
+
+evalue.obj:    	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.obj:       	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.obj:   	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.obj:    	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.obj:    	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.obj:      	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.obj:       	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.obj:  	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.obj:   	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.obj:       	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.obj:      	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.obj:      	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.obj:      	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.obj:      	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.obj:      	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.obj:      	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.obj:      	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.obj:      	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.obj:      	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.obj:      	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.obj:      	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.obj:      	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.obj:      	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.obj:      	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.obj:      	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.obj:      	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.obj:      	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.obj:      	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.obj:      	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.obj:      	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.obj:      	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.obj:      	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.obj:   	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.obj:  	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.obj:     	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.obj:  	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.obj:     	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.obj:  	solution.cpp include.h myexcept.h solution.h
+
+garch.obj:     	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt.exe
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example.exe
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc.exe
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex.exe
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex.exe
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch.exe
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_cc.mak
===================================================================
RCS file: Shared/newmat/extra/nm_cc.mak
diff -N Shared/newmat/extra/nm_cc.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_cc.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,182 @@
+CXX = CC
+CXXFLAGS = -O2
+
+DIFF = ./sdiff
+PRE = ./
+
+
+.SUFFIXES:
+.SUFFIXES: .a .o .c .cpp
+
+.cpp.o:
+		rm -f $*.cxx
+		ln $*.cpp $*.cxx  
+		$(CXX) $(CXXFLAGS) -c $*.cxx
+		rm $*.cxx  
+
+everything:    	tmt example test_exc nl_ex sl_ex garch 
+
+newmat_lobj = newmat1.o newmat2.o newmat3.o newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o newmatex.o bandmat.o submat.o myexcept.o cholesky.o evalue.o fft.o hholder.o jacobi.o newfft.o sort.o svd.o newmatrm.o newmat9.o
+
+libnewmat.a:   	$(newmat_lobj)
+		$(AR) cr $@ $(newmat_lobj)
+		ranlib $@
+
+tmt_obj = tmt.o tmt1.o tmt2.o tmt3.o tmt4.o tmt5.o tmt6.o tmt7.o tmt8.o tmt9.o tmta.o tmtb.o tmtc.o tmtd.o tmte.o tmtf.o tmtg.o tmth.o tmti.o tmtj.o tmtk.o tmtl.o tmtm.o
+
+tmt:           	$(tmt_obj) libnewmat.a
+		$(CXX) -o $@ $(tmt_obj) -L. -lnewmat -lm
+
+example_obj = example.o
+
+example:       	$(example_obj) libnewmat.a
+		$(CXX) -o $@ $(example_obj) -L. -lnewmat -lm
+
+test_exc_obj = test_exc.o
+
+test_exc:      	$(test_exc_obj) libnewmat.a
+		$(CXX) -o $@ $(test_exc_obj) -L. -lnewmat -lm
+
+nl_ex_obj = nl_ex.o newmatnl.o
+
+nl_ex:         	$(nl_ex_obj) libnewmat.a
+		$(CXX) -o $@ $(nl_ex_obj) -L. -lnewmat -lm
+
+sl_ex_obj = sl_ex.o solution.o myexcept.o
+
+sl_ex:         	$(sl_ex_obj)
+		$(CXX) -o $@ $(sl_ex_obj) -L. -lm
+
+garch_obj = garch.o newmatnl.o
+
+garch:         	$(garch_obj) libnewmat.a
+		$(CXX) -o $@ $(garch_obj) -L. -lnewmat -lm
+
+newmat1.o:     	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.o:     	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.o:     	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.o:     	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.o:     	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.o:     	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.o:     	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.o:     	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.o:    	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.o:     	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.o:      	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.o:    	myexcept.cpp include.h myexcept.h
+
+cholesky.o:    	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.o:      	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.o:         	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.o:     	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.o:      	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.o:      	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.o:        	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.o:         	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.o:    	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.o:     	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.o:         	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.o:        	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.o:        	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.o:        	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.o:        	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.o:        	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.o:        	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.o:        	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.o:        	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.o:        	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.o:        	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.o:        	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.o:        	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.o:        	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.o:        	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.o:        	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.o:        	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.o:        	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.o:        	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.o:        	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.o:        	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.o:        	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.o:        	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.o:     	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.o:    	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.o:       	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.o:    	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.o:       	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.o:    	solution.cpp include.h myexcept.h solution.h
+
+garch.o:       	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_gnu.mak
===================================================================
RCS file: Shared/newmat/extra/nm_gnu.mak
diff -N Shared/newmat/extra/nm_gnu.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_gnu.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,177 @@
+CXX = g++
+CXXFLAGS = -O2 -Wall
+
+DIFF = ./sdiff
+PRE = ./
+MAJOR = 1
+MINOR = 0
+
+%.o:           	%.cpp
+		$(CXX) $(CXXFLAGS) -c $*.cpp
+
+everything:    	tmt example test_exc nl_ex sl_ex garch 
+
+newmat_lobj = newmat1.o newmat2.o newmat3.o newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o newmatex.o bandmat.o submat.o myexcept.o cholesky.o evalue.o fft.o hholder.o jacobi.o newfft.o sort.o svd.o newmatrm.o newmat9.o
+
+libnewmat.a:   	$(newmat_lobj)
+		$(AR) cr $@ $(newmat_lobj)
+		ranlib $@
+
+tmt_obj = tmt.o tmt1.o tmt2.o tmt3.o tmt4.o tmt5.o tmt6.o tmt7.o tmt8.o tmt9.o tmta.o tmtb.o tmtc.o tmtd.o tmte.o tmtf.o tmtg.o tmth.o tmti.o tmtj.o tmtk.o tmtl.o tmtm.o
+
+tmt:           	$(tmt_obj) libnewmat.a
+		$(CXX) -o $@ $(tmt_obj) -L. -lnewmat -lm
+
+example_obj = example.o
+
+example:       	$(example_obj) libnewmat.a
+		$(CXX) -o $@ $(example_obj) -L. -lnewmat -lm
+
+test_exc_obj = test_exc.o
+
+test_exc:      	$(test_exc_obj) libnewmat.a
+		$(CXX) -o $@ $(test_exc_obj) -L. -lnewmat -lm
+
+nl_ex_obj = nl_ex.o newmatnl.o
+
+nl_ex:         	$(nl_ex_obj) libnewmat.a
+		$(CXX) -o $@ $(nl_ex_obj) -L. -lnewmat -lm
+
+sl_ex_obj = sl_ex.o solution.o myexcept.o
+
+sl_ex:         	$(sl_ex_obj)
+		$(CXX) -o $@ $(sl_ex_obj) -L. -lm
+
+garch_obj = garch.o newmatnl.o
+
+garch:         	$(garch_obj) libnewmat.a
+		$(CXX) -o $@ $(garch_obj) -L. -lnewmat -lm
+
+newmat1.o:     	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.o:     	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.o:     	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.o:     	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.o:     	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.o:     	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.o:     	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.o:     	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.o:    	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.o:     	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.o:      	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.o:    	myexcept.cpp include.h myexcept.h
+
+cholesky.o:    	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.o:      	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.o:         	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.o:     	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.o:      	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.o:      	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.o:        	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.o:         	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.o:    	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.o:     	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.o:         	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.o:        	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.o:        	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.o:        	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.o:        	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.o:        	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.o:        	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.o:        	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.o:        	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.o:        	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.o:        	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.o:        	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.o:        	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.o:        	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.o:        	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.o:        	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.o:        	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.o:        	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.o:        	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.o:        	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.o:        	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.o:        	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.o:        	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.o:     	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.o:    	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.o:       	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.o:    	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.o:       	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.o:    	solution.cpp include.h myexcept.h solution.h
+
+garch.o:       	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_i5.mak
===================================================================
RCS file: Shared/newmat/extra/nm_i5.mak
diff -N Shared/newmat/extra/nm_i5.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_i5.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,176 @@
+
+conlibs = libm.lib libc.lib
+
+DIFF = sdiff
+PRE =
+
+.SUFFIXES: .cpp
+
+.cpp.obj:
+		icl -c -GX -GR $*.cpp
+
+everything:    	tmt.exe example.exe test_exc.exe nl_ex.exe sl_ex.exe garch.exe 
+
+newmat_lobj = newmat1.obj newmat2.obj newmat3.obj newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj newmatex.obj bandmat.obj submat.obj myexcept.obj cholesky.obj evalue.obj fft.obj hholder.obj jacobi.obj newfft.obj sort.obj svd.obj newmatrm.obj newmat9.obj
+
+newmat.lib:    	$(newmat_lobj)
+		lib -Out:$@ $(newmat_lobj)
+
+tmt_obj = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj tmtm.obj
+
+tmt.exe:       	$(tmt_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(tmt_obj) newmat.lib
+
+example_obj = example.obj
+
+example.exe:   	$(example_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(example_obj) newmat.lib
+
+test_exc_obj = test_exc.obj
+
+test_exc.exe:  	$(test_exc_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(test_exc_obj) newmat.lib
+
+nl_ex_obj = nl_ex.obj newmatnl.obj
+
+nl_ex.exe:     	$(nl_ex_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(nl_ex_obj) newmat.lib
+
+sl_ex_obj = sl_ex.obj solution.obj myexcept.obj
+
+sl_ex.exe:     	$(sl_ex_obj)
+		link -Out:$@ $(conlibs) $(sl_ex_obj)
+
+garch_obj = garch.obj newmatnl.obj
+
+garch.exe:     	$(garch_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(garch_obj) newmat.lib
+
+newmat1.obj:   	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.obj:   	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.obj:   	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.obj:   	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.obj:   	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.obj:   	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.obj:   	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.obj:   	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.obj:  	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.obj:   	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.obj:    	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.obj:  	myexcept.cpp include.h myexcept.h
+
+cholesky.obj:  	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.obj:    	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.obj:       	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.obj:   	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.obj:    	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.obj:    	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.obj:      	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.obj:       	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.obj:  	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.obj:   	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.obj:       	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.obj:      	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.obj:      	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.obj:      	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.obj:      	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.obj:      	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.obj:      	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.obj:      	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.obj:      	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.obj:      	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.obj:      	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.obj:      	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.obj:      	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.obj:      	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.obj:      	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.obj:      	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.obj:      	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.obj:      	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.obj:      	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.obj:      	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.obj:      	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.obj:      	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.obj:      	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.obj:   	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.obj:  	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.obj:     	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.obj:  	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.obj:     	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.obj:  	solution.cpp include.h myexcept.h solution.h
+
+garch.obj:     	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt.exe
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example.exe
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc.exe
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex.exe
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex.exe
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch.exe
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_il5.mak
===================================================================
RCS file: Shared/newmat/extra/nm_il5.mak
diff -N Shared/newmat/extra/nm_il5.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_il5.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,177 @@
+CXX = icc
+CXXFLAGS = -O2 -Kc++eh -Krtti
+
+DIFF = ./sdiff
+PRE = ./
+MAJOR = 101
+MINOR = 0
+
+%.o:           	%.cpp
+		$(CXX) $(CXXFLAGS) -c $*.cpp
+
+everything:    	tmt example test_exc nl_ex sl_ex garch 
+
+newmat_lobj = newmat1.o newmat2.o newmat3.o newmat4.o newmat5.o newmat6.o newmat7.o newmat8.o newmatex.o bandmat.o submat.o myexcept.o cholesky.o evalue.o fft.o hholder.o jacobi.o newfft.o sort.o svd.o newmatrm.o newmat9.o
+
+libnewmat.a:   	$(newmat_lobj)
+		$(AR) -cr $@ $(newmat_lobj)
+		ranlib $@
+
+tmt_obj = tmt.o tmt1.o tmt2.o tmt3.o tmt4.o tmt5.o tmt6.o tmt7.o tmt8.o tmt9.o tmta.o tmtb.o tmtc.o tmtd.o tmte.o tmtf.o tmtg.o tmth.o tmti.o tmtj.o tmtk.o tmtl.o tmtm.o
+
+tmt:           	$(tmt_obj) libnewmat.a
+		$(CXX) -o $@ $(tmt_obj) -L. -lnewmat -lm
+
+example_obj = example.o
+
+example:       	$(example_obj) libnewmat.a
+		$(CXX) -o $@ $(example_obj) -L. -lnewmat -lm
+
+test_exc_obj = test_exc.o
+
+test_exc:      	$(test_exc_obj) libnewmat.a
+		$(CXX) -o $@ $(test_exc_obj) -L. -lnewmat -lm
+
+nl_ex_obj = nl_ex.o newmatnl.o
+
+nl_ex:         	$(nl_ex_obj) libnewmat.a
+		$(CXX) -o $@ $(nl_ex_obj) -L. -lnewmat -lm
+
+sl_ex_obj = sl_ex.o solution.o myexcept.o
+
+sl_ex:         	$(sl_ex_obj)
+		$(CXX) -o $@ $(sl_ex_obj) -L. -lm
+
+garch_obj = garch.o newmatnl.o
+
+garch:         	$(garch_obj) libnewmat.a
+		$(CXX) -o $@ $(garch_obj) -L. -lnewmat -lm
+
+newmat1.o:     	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.o:     	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.o:     	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.o:     	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.o:     	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.o:     	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.o:     	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.o:     	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.o:    	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.o:     	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.o:      	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.o:    	myexcept.cpp include.h myexcept.h
+
+cholesky.o:    	cholesky.cpp include.h newmat.h newmatrm.h myexcept.h
+
+evalue.o:      	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.o:         	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.o:     	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.o:      	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.o:      	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.o:        	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.o:         	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.o:    	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.o:     	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.o:         	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.o:        	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.o:        	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.o:        	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.o:        	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.o:        	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.o:        	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.o:        	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.o:        	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.o:        	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.o:        	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.o:        	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.o:        	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.o:        	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.o:        	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.o:        	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.o:        	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.o:        	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.o:        	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.o:        	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.o:        	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.o:        	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.o:        	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.o:     	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.o:    	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.o:       	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.o:    	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.o:       	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.o:    	solution.cpp include.h myexcept.h solution.h
+
+garch.o:       	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_m6.mak
===================================================================
RCS file: Shared/newmat/extra/nm_m6.mak
diff -N Shared/newmat/extra/nm_m6.mak
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_m6.mak	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,176 @@
+
+conlibs = libc.lib kernel32.lib
+
+DIFF = sdiff
+PRE =
+
+.SUFFIXES: .cpp
+
+.cpp.obj:
+		cl -c -W3 -Ox  -GX $*.cpp
+
+everything:    	tmt.exe example.exe test_exc.exe nl_ex.exe sl_ex.exe garch.exe 
+
+newmat_lobj = newmat1.obj newmat2.obj newmat3.obj newmat4.obj newmat5.obj newmat6.obj newmat7.obj newmat8.obj newmatex.obj bandmat.obj submat.obj myexcept.obj cholesky.obj evalue.obj fft.obj hholder.obj jacobi.obj newfft.obj sort.obj svd.obj newmatrm.obj newmat9.obj
+
+newmat.lib:    	$(newmat_lobj)
+		lib -Out:$@ $(newmat_lobj)
+
+tmt_obj = tmt.obj tmt1.obj tmt2.obj tmt3.obj tmt4.obj tmt5.obj tmt6.obj tmt7.obj tmt8.obj tmt9.obj tmta.obj tmtb.obj tmtc.obj tmtd.obj tmte.obj tmtf.obj tmtg.obj tmth.obj tmti.obj tmtj.obj tmtk.obj tmtl.obj tmtm.obj
+
+tmt.exe:       	$(tmt_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(tmt_obj) newmat.lib
+
+example_obj = example.obj
+
+example.exe:   	$(example_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(example_obj) newmat.lib
+
+test_exc_obj = test_exc.obj
+
+test_exc.exe:  	$(test_exc_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(test_exc_obj) newmat.lib
+
+nl_ex_obj = nl_ex.obj newmatnl.obj
+
+nl_ex.exe:     	$(nl_ex_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(nl_ex_obj) newmat.lib
+
+sl_ex_obj = sl_ex.obj solution.obj myexcept.obj
+
+sl_ex.exe:     	$(sl_ex_obj)
+		link -Out:$@ $(conlibs) $(sl_ex_obj)
+
+garch_obj = garch.obj newmatnl.obj
+
+garch.exe:     	$(garch_obj) newmat.lib
+		link -Out:$@ $(conlibs) $(garch_obj) newmat.lib
+
+newmat1.obj:   	newmat1.cpp newmat.h include.h myexcept.h
+
+newmat2.obj:   	newmat2.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat3.obj:   	newmat3.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat4.obj:   	newmat4.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat5.obj:   	newmat5.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat6.obj:   	newmat6.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat7.obj:   	newmat7.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+newmat8.obj:   	newmat8.cpp include.h newmat.h newmatrc.h precisio.h myexcept.h controlw.h
+
+newmatex.obj:  	newmatex.cpp include.h newmat.h myexcept.h
+
+bandmat.obj:   	bandmat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+submat.obj:    	submat.cpp include.h newmat.h newmatrc.h myexcept.h controlw.h
+
+myexcept.obj:  	myexcept.cpp include.h myexcept.h
+
+cholesky.obj:  	cholesky.cpp include.h newmat.h myexcept.h
+
+evalue.obj:    	evalue.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+fft.obj:       	fft.cpp include.h newmatap.h newmat.h myexcept.h
+
+hholder.obj:   	hholder.cpp include.h newmatap.h newmat.h myexcept.h
+
+jacobi.obj:    	jacobi.cpp include.h newmatap.h precisio.h newmatrm.h newmat.h myexcept.h
+
+newfft.obj:    	newfft.cpp newmatap.h newmat.h include.h myexcept.h
+
+sort.obj:      	sort.cpp include.h newmatap.h newmat.h myexcept.h
+
+svd.obj:       	svd.cpp include.h newmatap.h newmatrm.h precisio.h newmat.h myexcept.h
+
+newmatrm.obj:  	newmatrm.cpp newmat.h newmatrm.h include.h myexcept.h
+
+newmat9.obj:   	newmat9.cpp include.h newmat.h newmatio.h newmatrc.h myexcept.h controlw.h
+
+tmt.obj:       	tmt.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt1.obj:      	tmt1.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt2.obj:      	tmt2.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt3.obj:      	tmt3.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt4.obj:      	tmt4.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt5.obj:      	tmt5.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt6.obj:      	tmt6.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt7.obj:      	tmt7.cpp include.h newmat.h tmt.h myexcept.h
+
+tmt8.obj:      	tmt8.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmt9.obj:      	tmt9.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmta.obj:      	tmta.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtb.obj:      	tmtb.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtc.obj:      	tmtc.cpp include.h newmat.h tmt.h myexcept.h
+
+tmtd.obj:      	tmtd.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmte.obj:      	tmte.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtf.obj:      	tmtf.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtg.obj:      	tmtg.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmth.obj:      	tmth.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmti.obj:      	tmti.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtj.obj:      	tmtj.cpp include.h newmatap.h tmt.h newmat.h myexcept.h
+
+tmtk.obj:      	tmtk.cpp include.h newmatap.h newmatio.h tmt.h newmat.h myexcept.h
+
+tmtl.obj:      	tmtl.cpp newmat.h tmt.h include.h myexcept.h
+
+tmtm.obj:      	tmtm.cpp newmat.h newmatio.h tmt.h include.h myexcept.h
+
+example.obj:   	example.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+test_exc.obj:  	test_exc.cpp newmatap.h newmatio.h newmat.h include.h myexcept.h
+
+nl_ex.obj:     	nl_ex.cpp newmatnl.h newmatio.h newmat.h include.h myexcept.h
+
+newmatnl.obj:  	newmatnl.cpp newmatap.h newmatnl.h newmat.h include.h myexcept.h
+
+sl_ex.obj:     	sl_ex.cpp include.h solution.h myexcept.h
+
+solution.obj:  	solution.cpp include.h myexcept.h solution.h
+
+garch.obj:     	garch.cpp newmatap.h newmatio.h newmatnl.h newmat.h include.h myexcept.h
+
+tmt.txx:       	tmt.exe
+		$(PRE)tmt > tmt.txx
+		$(DIFF) tmt.txt tmt.txx
+
+example.txx:   	example.exe
+		$(PRE)example > example.txx
+		$(DIFF) example.txt example.txx
+
+test_exc.txx:  	test_exc.exe
+		$(PRE)test_exc > test_exc.txx
+		$(DIFF) test_exc.txt test_exc.txx
+
+nl_ex.txx:     	nl_ex.exe
+		$(PRE)nl_ex > nl_ex.txx
+		$(DIFF) nl_ex.txt nl_ex.txx
+
+sl_ex.txx:     	sl_ex.exe
+		$(PRE)sl_ex > sl_ex.txx
+		$(DIFF) sl_ex.txt sl_ex.txx
+
+garch.txx:     	garch.exe
+		$(PRE)garch > garch.txx
+		$(DIFF) garch.txt garch.txx
+
Index: Shared/newmat/extra/nm_targ.txt
===================================================================
RCS file: Shared/newmat/extra/nm_targ.txt
diff -N Shared/newmat/extra/nm_targ.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/nm_targ.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,7 @@
+newmat.lfl
+tmt
+example
+test_exc
+nl_ex
+sl_ex
+garch
Index: Shared/newmat/extra/sl_ex.cpp
===================================================================
RCS file: Shared/newmat/extra/sl_ex.cpp
diff -N Shared/newmat/extra/sl_ex.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/sl_ex.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,33 @@
+// This is an example of the use of solution to find the cube root of 
+// the integers -10 to 10
+
+// you will need to compile and link solution.cpp and except.cpp
+
+#define WANT_STREAM
+#define WANT_MATH
+
+#include "include.h"
+#include "solution.h"
+
+#ifdef use_namespace
+using namespace RBD_LIBRARIES;
+#endif
+
+
+// the cube class
+
+class Cube : public R1_R1
+{ Real operator()() { return x*x*x; } };
+
+int main()
+{
+   // construct the Cube object
+   Cube cube;
+   // and then the solve object
+   OneDimSolve cube_root(cube);
+   // Now do the solves
+   for (int i=-10; i<=10; i++)
+      cout << i << "   "  << cube_root.Solve(i,0,1.5) << endl;
+   return 0;
+}
+
Index: Shared/newmat/extra/sl_ex.txt
===================================================================
RCS file: Shared/newmat/extra/sl_ex.txt
diff -N Shared/newmat/extra/sl_ex.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/sl_ex.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,21 @@
+-10   -2.15443
+-9   -2.08008
+-8   -2
+-7   -1.91293
+-6   -1.81712
+-5   -1.70998
+-4   -1.5874
+-3   -1.44225
+-2   -1.25992
+-1   -1.00001
+0   0
+1   1.00001
+2   1.25992
+3   1.44225
+4   1.58741
+5   1.70998
+6   1.81712
+7   1.91293
+8   2
+9   2.08008
+10   2.15443
Index: Shared/newmat/extra/solution.cpp
===================================================================
RCS file: Shared/newmat/extra/solution.cpp
diff -N Shared/newmat/extra/solution.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/solution.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,199 @@
+//$$ solution.cpp                    // solve routines
+
+// Copyright (C) 1994: R B Davies
+
+
+#define WANT_STREAM                  // include.h will get stream fns
+#define WANT_MATH                    // include.h will get math fns
+
+#include "include.h"
+#include "myexcept.h"
+
+#include "solution.h"
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+void R1_R1::Set(Real X)
+{
+   if ((!minXinf && X <= minX) || (!maxXinf && X >= maxX))
+       Throw(SolutionException("X value out of range"));
+   x = X; xSet = true;
+}
+
+R1_R1::operator Real()
+{
+   if (!xSet) Throw(SolutionException("Value of X not set"));
+   Real y = operator()();
+   return y;
+}
+
+unsigned long SolutionException::Select;
+
+SolutionException::SolutionException(const char* a_what) : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("Error detected by solution package\n");
+   AddMessage(a_what); AddMessage("\n");
+   if (a_what) Tracer::AddTrace();
+};
+
+inline Real square(Real x) { return x*x; }
+
+void OneDimSolve::LookAt(int V)
+{
+   lim--;
+   if (!lim) Throw(SolutionException("Does not converge"));
+   Last = V;
+   Real yy = function(x[V]) - YY;
+   Finish = (fabs(yy) <= accY) || (Captured && fabs(x[L]-x[U]) <= accX );
+   y[V] = vpol*yy;
+}
+
+void OneDimSolve::HFlip() { hpol=-hpol; State(U,C,L); }
+
+void OneDimSolve::VFlip()
+   { vpol = -vpol; y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2]; }
+
+void OneDimSolve::Flip()
+{
+   hpol=-hpol; vpol=-vpol; State(U,C,L);
+   y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2];
+}
+
+void OneDimSolve::State(int I, int J, int K) { L=I; C=J; U=K; }
+
+void OneDimSolve::Linear(int I, int J, int K)
+{
+   x[J] = (x[I]*y[K] - x[K]*y[I])/(y[K] - y[I]);
+   // cout << "Linear\n";
+}
+
+void OneDimSolve::Quadratic(int I, int J, int K)
+{
+   // result to overwrite I
+   Real YJK, YIK, YIJ, XKI, XKJ;
+   YJK = y[J] - y[K]; YIK = y[I] - y[K]; YIJ = y[I] - y[J];
+   XKI = (x[K] - x[I]);
+   XKJ = (x[K]*y[J] - x[J]*y[K])/YJK;
+   if ( square(YJK/YIK)>(x[K] - x[J])/XKI ||
+      square(YIJ/YIK)>(x[J] - x[I])/XKI )
+   {
+      x[I] = XKJ;
+      // cout << "Quadratic - exceptional\n";
+   }
+   else
+   {
+      XKI = (x[K]*y[I] - x[I]*y[K])/YIK;
+      x[I] = (XKJ*y[I] - XKI*y[J])/YIJ;
+      // cout << "Quadratic - normal\n";
+   }
+}
+
+Real OneDimSolve::Solve(Real Y, Real X, Real Dev, int Lim)
+{
+   enum Loop { start, captured1, captured2, binary, finish };
+   Tracer et("OneDimSolve::Solve");
+   lim=Lim; Captured = false;
+   if (Dev==0.0) Throw(SolutionException("Dev is zero"));
+   L=0; C=1; U=2; vpol=1; hpol=1; y[C]=0.0; y[U]=0.0;
+   if (Dev<0.0) { hpol=-1; Dev = -Dev; }
+   YY=Y;                                // target value
+   x[L] = X;                            // initial trial value
+   if (!function.IsValid(X))
+      Throw(SolutionException("Starting value is invalid"));
+   Loop TheLoop = start;
+   for (;;)
+   {
+      switch (TheLoop)
+      {
+      case start:
+         LookAt(L); if (Finish) { TheLoop = finish; break; }
+         if (y[L]>0.0) VFlip();               // so Y[L] < 0
+
+         x[U] = X + Dev * hpol;
+         if (!function.maxXinf && x[U] > function.maxX)
+            x[U] = (function.maxX + X) / 2.0;
+         if (!function.minXinf && x[U] < function.minX)
+            x[U] = (function.minX + X) / 2.0;
+
+         LookAt(U); if (Finish) { TheLoop = finish; break; }
+         if (y[U] > 0.0) { TheLoop = captured1; Captured = true; break; }
+         if (y[U] == y[L])
+            Throw(SolutionException("Function is flat"));
+         if (y[U] < y[L]) HFlip();             // Change direction
+         State(L,U,C);
+         for (i=0; i<20; i++)
+         {
+            // cout << "Searching for crossing point\n";
+            // Have L C then crossing point, Y[L]<Y[C]<0
+            x[U] = x[C] + Dev * hpol;
+            if (!function.maxXinf && x[U] > function.maxX)
+            x[U] = (function.maxX + x[C]) / 2.0;
+            if (!function.minXinf && x[U] < function.minX)
+            x[U] = (function.minX + x[C]) / 2.0;
+
+            LookAt(U); if (Finish) { TheLoop = finish; break; }
+            if (y[U] > 0) { TheLoop = captured2; Captured = true; break; }
+            if (y[U] < y[C])
+                Throw(SolutionException("Function is not monotone"));
+            Dev *= 2.0;
+            State(C,U,L);
+         }
+         if (TheLoop != start ) break;
+         Throw(SolutionException("Cannot locate a crossing point"));
+
+      case captured1:
+         // cout << "Captured - 1\n";
+         // We have 2 points L and U with crossing between them
+         Linear(L,C,U);                   // linear interpolation
+                                          // - result to C
+         LookAt(C); if (Finish) { TheLoop = finish; break; }
+         if (y[C] > 0.0) Flip();            // Want y[C] < 0
+         if (y[C] < 0.5*y[L]) { State(C,L,U); TheLoop = binary; break; }
+
+      case captured2:
+         // cout << "Captured - 2\n";
+         // We have L,C before crossing, U after crossing
+         Quadratic(L,C,U);                // quad interpolation
+                                          // - result to L
+         State(C,L,U);
+         if ((x[C] - x[L])*hpol <= 0.0 || (x[C] - x[U])*hpol >= 0.0)
+            { TheLoop = captured1; break; }
+         LookAt(C); if (Finish) { TheLoop = finish; break; }
+         // cout << "Through first stage\n";
+         if (y[C] > 0.0) Flip();
+         if (y[C] > 0.5*y[L]) { TheLoop = captured2; break; }
+         else { State(C,L,U); TheLoop = captured1; break; }
+
+      case binary:
+         // We have L, U around crossing - do binary search
+         // cout << "Binary\n";
+         for (i=3; i; i--)
+         {
+            x[C] = 0.5*(x[L]+x[U]);
+            LookAt(C); if (Finish) { TheLoop = finish; break; }
+            if (y[C]>0.0) State(L,U,C); else State(C,L,U);
+         }
+         if (TheLoop != binary) break;
+         TheLoop = captured1; break;
+
+      case finish:
+	 return x[Last];
+
+      }
+   }
+}
+
+bool R1_R1::IsValid(Real X)
+{
+   Set(X);
+   return (minXinf || x > minX) && (maxXinf || x < maxX);
+}
+
+#ifdef use_namespace
+}
+#endif
+
Index: Shared/newmat/extra/solution.h
===================================================================
RCS file: Shared/newmat/extra/solution.h
diff -N Shared/newmat/extra/solution.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/solution.h	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,93 @@
+//$$ solution.h                      // solve routines
+
+#include "myexcept.h"
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+// Solve the equation f(x)=y for x where f is a monotone continuous
+// function of x
+// Essentially Brent s method
+
+// You need to derive a class from R1_R1 and override "operator()"
+// with the function you want to solve.
+// Use an object from this class in OneDimSolve
+
+class R1_R1
+{
+   // the prototype for a Real function of a Real variable
+   // you need to derive your function from this one and put in your
+   // function for operator() at least. You probably also want to set up a
+   // constructor to put in additional parameter values (e.g. that will not
+   // vary during a solve)
+
+protected:
+   Real x;                             // Current x value
+   bool xSet;                          // true if a value assigned to x
+
+public:
+   Real minX, maxX;                    // range of value x
+   bool minXinf, maxXinf;              // true if these are infinite
+   R1_R1() : xSet(false), minXinf(true), maxXinf(true) {}
+   virtual Real operator()() = 0;      // function value at current x
+                                       // set current x
+   virtual void Set(Real X);           // set x, check OK
+   Real operator()(Real X) { Set(X); return operator()(); }
+                                       // set x, return value
+   virtual bool IsValid(Real X);
+   operator Real();                    // implicit conversion
+};
+
+class SolutionException : public BaseException
+{
+public:
+   static unsigned long Select;
+   SolutionException(const char* a_what = 0);
+};
+
+class OneDimSolve
+{
+   R1_R1& function;                     // reference to the function
+   Real accX;                           // accuracy in X direction
+   Real accY;                           // accuracy in Y direction
+   int lim;                             // maximum number of iterations
+
+public:
+   OneDimSolve(R1_R1& f, Real AccY = 0.0001, Real AccX = 0.0)
+      : function(f), accX(AccX), accY(AccY) {}
+                       // f is an R1_R1 function
+   Real Solve(Real Y, Real X, Real Dev, int Lim=100);
+                       // Solve for x in Y=f(x)
+                       // X is the initial trial value of x
+                       // X+Dev is the second trial value
+                       // program returns a value of x such that
+                       // |Y-f(x)| <= accY or |f.inv(Y)-x| <= accX
+
+private:
+   Real x[3], y[3];                         // Trial values of X and Y
+   int L,C,U,Last;                          // Locations of trial values
+   int vpol, hpol;                          // polarities
+   Real YY;                                 // target value
+   int i;
+   void LookAt(int);                        // get new value of function
+   bool Finish;                             // true if LookAt finds conv.
+   bool Captured;                           // true when target surrounded
+   void VFlip();
+   void HFlip();
+   void Flip();
+   void State(int I, int J, int K);
+   void Linear(int, int, int);
+   void Quadratic(int, int, int);
+};
+
+
+#ifdef use_namespace
+}
+#endif
+
+// body file: solution.cpp
+
+
+
Index: Shared/newmat/extra/test_exc.cpp
===================================================================
RCS file: Shared/newmat/extra/test_exc.cpp
diff -N Shared/newmat/extra/test_exc.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/test_exc.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,188 @@
+#define WANT_STREAM
+
+#include "newmatap.h"
+#include "newmatio.h"              // to help namespace with VC++ 5
+
+#ifdef use_namespace
+using namespace RBD_LIBRARIES;
+#endif
+
+//#include <except.h>             // if you want to use set_terminate
+
+/**************************** test exceptions ******************************/
+
+
+
+int main()
+{
+   // activate the next expression if you want to use compiler supported
+   // exceptions and you want Terminate to catch uncaught exceptions
+   // set_terminate(Terminate);
+   Real* s1; Real* s2; Real* s3; Real* s4;
+   // Forces cout to allocate memory at beginning
+   cout << "\nThis tests the exception system, so you will get\n" <<
+      "a long list of error messages\n\n";
+   cout << "\nPrint a real number (may help lost memory test): " << 3.14159265 << "\n";
+   // Throw exception to set up exception buffer
+   Try { Throw(BaseException("Just a dummy\n")); }
+   CatchAll {};
+   { Matrix A1(40,200); s1 = A1.Store(); }
+   { Matrix A1(1,1); s3 = A1.Store(); }
+   {
+      Tracer et("Test");
+
+      Try
+      {
+         Tracer et("Try block");
+
+
+
+         cout << "-----------------------------------------\n\n";
+         Matrix A(2,3), B(4,5); A = 1; B = 2;
+         cout << "Incompatible dimensions\n";
+         et.ReName("Block A");
+         Try { Matrix C = A + B; }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Bad index\n";
+         et.ReName("Block B");
+         Try { Real f = A(3,3); cout << f << endl; }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Illegal conversion\n";
+         et.ReName("Block C");
+         Try { UpperTriangularMatrix U = A; }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Invert non-square matrix - 1\n";
+         et.ReName("Block D");
+         Try { CroutMatrix X = A; }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Invert non-square matrix - 2\n";
+         et.ReName("Block E");
+         Try { Matrix X = A.i(); }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Non 1x1 matrix to scalar\n";
+         et.ReName("Block F");
+         Try { Real f = A.AsScalar(); cout << f << endl; }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Matrix to vector\n";
+         et.ReName("Block G");
+         Try { ColumnVector CV = A;}
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Invert singular matrix\n";
+         et.ReName("Block H");
+         Try { Matrix X(2,2); X<<1<<2<<2<<4; X = X.i(); }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "SubMatrix error\n";
+         et.ReName("Block I");
+         Try { Matrix X = A.Row(3); }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "SubMatrix error\n";
+         et.ReName("Block J");
+         Try { Matrix X = A.Row(0); }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Cholesky error\n";
+         et.ReName("Block K");
+         Try
+         {
+            SymmetricMatrix SM(50); SM = 10;
+            LowerTriangularMatrix L = Cholesky(SM);
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Inequality error\n";
+         et.ReName("Block L");
+         Try
+         {
+            Matrix A(10,10), B(10,10); A = 10; B = 20;
+            if ( A < B) A = B;
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Maximum of empty matrix\n";
+         et.ReName("Block M");
+         Try
+         {
+            Matrix A(10,20); A = 5; Matrix B=A.Rows(6,5);
+            MaximumAbsoluteValue(B);
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Incorrectly ReSizing band matrix\n";
+         et.ReName("Block N");
+         Try
+         {
+            BandMatrix A(20,5,3); A = 5; UpperBandMatrix B;
+            B.ReSize(A);
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "Incorrectly ReSizing symmetric band matrix\n";
+         et.ReName("Block M");
+         Try
+         {
+            BandMatrix A(20,5,3); A = 5; SymmetricBandMatrix B;
+            B.ReSize(A);
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+         cout << "ReSize CroutMatrix\n";
+         et.ReName("Block O");
+         Try
+         {
+            Matrix A(3,3); A = 0; A(1,1) = A(2,2) = A(3,3) = 1;
+            CroutMatrix B = A;;
+            B.ReSize(A);
+         }
+         CatchAll { cout << BaseException::what() << endl; }
+         cout << "-----------------------------------------\n\n";
+
+
+      }
+      CatchAll { cout << "\nException generated in test program\n\n"; }
+   }
+
+   cout << "\nEnd test\n";
+   { Matrix A1(40,200); s2 = A1.Store(); }
+   cout << "\n(The following memory checks are probably not valid with all\n";
+   cout << "compilers - see documentation)\n";
+   cout << "\nChecking for lost memory: "
+      << (unsigned long)s1 << " " << (unsigned long)s2 << " ";
+   if (s1 != s2) cout << " - error\n"; else cout << " - ok\n";
+   { Matrix A1(1,1); s4 = A1.Store(); }
+   cout << "\nChecking for lost memory: "
+      << (unsigned long)s3 << " " << (unsigned long)s4 << " ";
+   if (s3 != s4) cout << " - error\n\n"; else cout << " - ok\n\n";
+
+
+#ifdef DO_FREE_CHECK
+   FreeCheck::Status();
+#endif
+
+//   Throw(Runtime_error("Exception outside try block"));
+
+   return 0;
+}
Index: Shared/newmat/extra/test_exc.txt
===================================================================
RCS file: Shared/newmat/extra/test_exc.txt
diff -N Shared/newmat/extra/test_exc.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/test_exc.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,188 @@
+
+This tests the exception system, so you will get
+a long list of error messages
+
+
+Print a real number (may help lost memory test): 3.14159
+-----------------------------------------
+
+Incompatible dimensions
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: incompatible dimensions
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+MatrixType = Rect   # Rows = 4; # Cols = 5
+Trace: AddedMatrix::Evaluate; Block A; Test.
+
+-----------------------------------------
+
+Bad index
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: index error: requested indices = 3, 3
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+Trace: Block B; Test.
+
+-----------------------------------------
+
+Illegal conversion
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: Illegal Conversion
+MatrixTypes = Rect ; UT   
+
+Trace: Block C; Test.
+
+-----------------------------------------
+
+Invert non-square matrix - 1
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: matrix is not square
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+Trace: CroutMatrix; Block D; Test.
+
+-----------------------------------------
+
+Invert non-square matrix - 2
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: matrix is not square
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+Trace: GeneralSolvI; InvertedMatrix::Evaluate; Block E; Test.
+
+-----------------------------------------
+
+Non 1x1 matrix to scalar
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: Cannot convert to scalar
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+Trace: AsScalar; Block F; Test.
+
+-----------------------------------------
+
+Matrix to vector
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: cannot convert matrix to vector
+
+MatrixType = Rect   # Rows = 2; # Cols = 3
+Trace: ColumnVector; Block G; Test.
+
+-----------------------------------------
+
+Invert singular matrix
+
+
+An exception has been thrown
+Runtime error:- detected by Newmat: matrix is singular
+
+MatrixType = Crout  # Rows = 2; # Cols = 2
+Trace: Crout(lubksb); GeneralSolvI; InvertedMatrix::Evaluate; Block H; Test.
+
+-----------------------------------------
+
+SubMatrix error
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: incompatible submatrix dimension
+
+Trace: SubMatrix(evaluate); Block I; Test.
+
+-----------------------------------------
+
+SubMatrix error
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: incompatible submatrix dimension
+
+Trace: SubMatrix(row); Block J; Test.
+
+-----------------------------------------
+
+Cholesky error
+
+
+An exception has been thrown
+Runtime error:- detected by Newmat: matrix not positive definite
+
+MatrixType = Sym    # Rows = 50; # Cols = 50
+Trace: Cholesky; Block K; Test.
+
+-----------------------------------------
+
+Inequality error
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: inequalities not defined for matrices
+
+Trace: Block L; Test.
+
+-----------------------------------------
+
+Maximum of empty matrix
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: Maximum or minimum of null matrix
+
+Trace: Block M; Test.
+
+-----------------------------------------
+
+Incorrectly ReSizing band matrix
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: UpperBandMatrix with non-zero lower band
+
+Trace: UpperBandMatrix::ReSize; Block N; Test.
+
+-----------------------------------------
+
+Incorrectly ReSizing symmetric band matrix
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: Upper and lower band-widths not equal
+
+Trace: SymmetricBandMatrix::ReSize(GM); Block M; Test.
+
+-----------------------------------------
+
+ReSize CroutMatrix
+
+
+An exception has been thrown
+Logic error:- detected by Newmat: ReSize not defined for this type of matrix
+
+Trace: GeneralMatrix::ReSize(GM); Block O; Test.
+
+-----------------------------------------
+
+
+End test
+
+(The following memory checks are probably not valid with all
+compilers - see documentation)
+
+Checking for lost memory: 8142064 8142064  - ok
+
+Checking for lost memory: 8142064 8142064  - ok
+
Index: Shared/newmat/extra/tmt.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt.cpp
diff -N Shared/newmat/extra/tmt.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,510 @@
+#define WANT_STREAM
+#define WANT_TIME
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+//using namespace NEWMAT;
+namespace NEWMAT {
+#endif
+
+
+/**************************** test program ******************************/
+
+
+class PrintCounter
+{
+   int count;
+   const char* s;
+public:
+   ~PrintCounter();
+   PrintCounter(const char * sx) : count(0), s(sx) {}
+   void operator++() { count++; }
+};
+
+PrintCounter PCZ("Number of non-zero matrices (should be 1) = ");
+PrintCounter PCN("Number of matrices tested                 = ");
+
+PrintCounter::~PrintCounter()
+{ cout << s << count << "\n"; }
+
+
+void Print(const Matrix& X)
+{
+   ++PCN;
+   cout << "\nMatrix type: " << X.Type().Value() << " (";
+   cout << X.Nrows() << ", ";
+   cout << X.Ncols() << ")\n\n";
+   if (X.IsZero()) { cout << "All elements are zero\n" << flush; return; }
+   int nr=X.Nrows(); int nc=X.Ncols();
+   for (int i=1; i<=nr; i++)
+   {
+      for (int j=1; j<=nc; j++)  cout << X(i,j) << "\t";
+      cout << "\n";
+   }
+   cout << flush; ++PCZ;
+}
+
+void Print(const UpperTriangularMatrix& X)
+{
+   ++PCN;
+   cout << "\nMatrix type: " << X.Type().Value() << " (";
+   cout << X.Nrows() << ", ";
+   cout << X.Ncols() << ")\n\n";
+   if (X.IsZero()) { cout << "All elements are zero\n" << flush; return; }
+   int nr=X.Nrows(); int nc=X.Ncols();
+   for (int i=1; i<=nr; i++)
+   {
+      int j;
+      for (j=1; j<i; j++) cout << "\t";
+      for (j=i; j<=nc; j++)  cout << X(i,j) << "\t";
+      cout << "\n";
+   }
+   cout << flush; ++PCZ;
+}
+
+void Print(const DiagonalMatrix& X)
+{
+   ++PCN;
+   cout << "\nMatrix type: " << X.Type().Value() << " (";
+   cout << X.Nrows() << ", ";
+   cout << X.Ncols() << ")\n\n";
+   if (X.IsZero()) { cout << "All elements are zero\n" << flush; return; }
+   int nr=X.Nrows(); int nc=X.Ncols();
+   for (int i=1; i<=nr; i++)
+   {
+      for (int j=1; j<i; j++) cout << "\t";
+      if (i<=nc) cout << X(i,i) << "\t";
+      cout << "\n";
+   }
+   cout << flush; ++PCZ;
+}
+
+void Print(const SymmetricMatrix& X)
+{
+   ++PCN;
+   cout << "\nMatrix type: " << X.Type().Value() << " (";
+   cout << X.Nrows() << ", ";
+   cout << X.Ncols() << ")\n\n";
+   if (X.IsZero()) { cout << "All elements are zero\n" << flush; return; }
+   int nr=X.Nrows(); int nc=X.Ncols();
+   for (int i=1; i<=nr; i++)
+   {
+      int j;
+      for (j=1; j<i; j++) cout << X(j,i) << "\t";
+      for (j=i; j<=nc; j++)  cout << X(i,j) << "\t";
+      cout << "\n";
+   }
+   cout << flush; ++PCZ;
+}
+
+void Print(const LowerTriangularMatrix& X)
+{
+   ++PCN;
+   cout << "\nMatrix type: " << X.Type().Value() << " (";
+   cout << X.Nrows() << ", ";
+   cout << X.Ncols() << ")\n\n";
+   if (X.IsZero()) { cout << "All elements are zero\n" << flush; return; }
+   int nr=X.Nrows();
+   for (int i=1; i<=nr; i++)
+   {
+      for (int j=1; j<=i; j++) cout << X(i,j) << "\t";
+      cout << "\n";
+   }
+   cout << flush; ++PCZ;
+}
+
+
+void Clean(Matrix& A, Real c)
+{
+   int nr = A.Nrows(); int nc = A.Ncols();
+   for (int i=1; i<=nr; i++)
+   {
+      for (int j=1; j<=nc; j++)
+      { Real a = A(i,j); if ((a < c) && (a > -c)) A(i,j) = 0.0; }
+   }
+}
+
+void Clean(DiagonalMatrix& A, Real c)
+{
+   int nr = A.Nrows();
+   for (int i=1; i<=nr; i++)
+   { Real a = A(i,i); if ((a < c) && (a > -c)) A(i,i) = 0.0; }
+}
+
+void PentiumCheck(Real N, Real D)
+{
+   Real R = N / D;
+   R = R * D - N;
+   if ( R > 1 || R < -1)
+      cout << "Pentium error detected: % error = " << 100 * R / N << "\n";
+}
+
+// random number generator class
+// See newran03 documentation for details
+
+MultWithCarry::MultWithCarry(double s)
+{
+   if (s>=1.0 || s<=0.0)
+      Throw(Logic_error("MultWithCarry: seed out of range"));
+   x = (unsigned long)(s * 4294967296.0);
+   crry = 1234567;
+}
+
+
+// carry out 32bit * 32bit multiply in software
+
+void MultWithCarry::NextValue()
+{
+   unsigned long  mult = 2083801278;
+   unsigned long  m_hi = mult >> 16;
+   unsigned long  m_lo = mult & 0xFFFF;
+
+   unsigned long  x_hi = x >> 16;
+   unsigned long  x_lo = x & 0xFFFF;
+
+   unsigned long  c_hi = crry >> 16;
+   unsigned long  c_lo = crry & 0xFFFF;
+
+   x = x_lo * m_lo + c_lo;
+   unsigned long axc = x_lo * m_hi + x_hi * m_lo + c_hi + (x >> 16);
+   crry = x_hi * m_hi + (axc >> 16);
+
+   x = (x & 0xFFFF) + (axc << 16);
+
+}
+
+Real MultWithCarry::Next() { NextValue(); return ((double)x + 0.5) / 4294967296.0; }
+
+// fill a matrix with values from the MultWithCarry random number generator
+void FillWithValues(MultWithCarry&MWC, Matrix& M)
+{
+   int nr = M.nrows();
+   int nc = M.ncols();
+   for (int i = 1; i <= nr; ++i) for (int j = 1; j <= nc; ++ j)
+   M(i, j) = MWC.Next();
+}
+   
+
+#ifdef use_namespace
+}
+using namespace NEWMAT;
+#endif
+
+
+//*************************** main program **********************************
+
+void TestTypeAdd();                            // test +
+void TestTypeMult();                           // test *
+void TestTypeConcat();                         // test |
+void TestTypeSP();                             // test SP
+void TestTypeKP();                             // test KP
+void TestTypeOrder();                          // test >=
+
+
+int main()
+{
+   time_lapse tl;      // measure program run time
+   Real* s1; Real* s2; Real* s3; Real* s4;
+   cout << "\nBegin test\n";   // Forces cout to allocate memory at beginning
+   cout << "Now print a real number: " << 3.14159265 << endl;
+   // Throw exception to set up exception buffer
+#ifndef DisableExceptions
+   Try { Throw(BaseException("Just a dummy\n")); }
+   CatchAll {}
+#else
+   cout << "Not doing exceptions\n";
+#endif
+   { Matrix A1(40,200); s1 = A1.Store(); }
+   { Matrix A1(1,1); s3 = A1.Store(); }
+   {
+      Tracer et("Matrix test program");
+
+      Matrix A(25,150);
+      {
+         int i;
+         RowVector A(8);
+         for (i=1;i<=7;i++) A(i)=0.0; A(8)=1.0;
+         Print(A);
+      }
+      cout << "\n";
+
+      TestTypeAdd(); TestTypeMult(); TestTypeConcat();
+      TestTypeSP(); TestTypeKP(); TestTypeOrder();
+
+      Try { 
+         trymat1();
+         trymat2();
+         trymat3();
+         trymat4();
+         trymat5();
+         trymat6();
+         trymat7();
+         trymat8();
+         trymat9();
+         trymata();
+         trymatb();
+         trymatc();
+         trymatd();
+         trymate();
+         trymatf();
+         trymatg();
+         trymath();
+         trymati();
+         trymatj();
+         trymatk();
+         trymatl();
+         trymatm();
+
+         cout << "\nEnd of tests\n";
+      }
+      CatchAll
+      {
+         cout << "\nTest program fails - exception generated\n\n";
+         cout << BaseException::what();
+      }
+
+
+   }
+
+   { Matrix A1(40,200); s2 = A1.Store(); }
+   cout << "\n(The following memory checks are probably not valid with all\n";
+   cout << "compilers - see documentation)\n";
+   cout << "\nChecking for lost memory: "
+      << (unsigned long)s1 << " " << (unsigned long)s2 << " ";
+   if (s1 != s2) cout << " - error\n\n"; else cout << " - ok\n\n";
+   { Matrix A1(1,1); s4 = A1.Store(); }
+   cout << "\nChecking for lost memory: "
+      << (unsigned long)s3 << " " << (unsigned long)s4 << " ";
+   if (s3 != s4) cout << " - error\n\n"; else cout << " - ok\n\n";
+
+   // check for Pentium bug
+   PentiumCheck(4195835L,3145727L);
+   PentiumCheck(5244795L,3932159L);
+
+#ifdef DO_FREE_CHECK
+   FreeCheck::Status();
+#endif
+   return 0;
+}
+
+
+
+
+//************************ test type manipulation **************************/
+
+
+// These functions may cause problems for Glockenspiel 2.0c; they are used
+// only for testing so you can delete them
+
+
+void TestTypeAdd()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << "+     ";
+   int i;
+   for (i=0; i<MatrixType::nTypes(); i++) cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+	{
+		cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+         cout << (list[j]+list[i]).Value() << " ";
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+void TestTypeMult()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << "*     ";
+   int i;
+   for (i=0; i<MatrixType::nTypes(); i++)
+      cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+   {
+		cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+         cout << (list[j]*list[i]).Value() << " ";
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+void TestTypeConcat()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << "|     ";
+   int i;
+   for (i=0; i<MatrixType::nTypes(); i++)
+      cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+   {
+		cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+         cout << (list[j] | list[i]).Value() << " ";
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+void TestTypeSP()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << "SP    ";
+   int i;
+   for (i=0; i<MatrixType::nTypes(); i++)
+		cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+   {
+		cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+         cout << (list[j].SP(list[i])).Value() << " ";
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+void TestTypeKP()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << "KP    ";
+   int i;
+   for (i=0; i<MatrixType::nTypes(); i++)
+		cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+   {
+		cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+         cout << (list[j].KP(list[i])).Value() << " ";
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+void TestTypeOrder()
+{
+   MatrixType list[12];
+   list[0] = MatrixType::UT;
+   list[1] = MatrixType::LT;
+   list[2] = MatrixType::Rt;
+   list[3] = MatrixType::Sq;
+   list[4] = MatrixType::Sm;
+   list[5] = MatrixType::Dg;
+   list[6] = MatrixType::BM;
+   list[7] = MatrixType::UB;
+   list[8] = MatrixType::LB;
+   list[9] = MatrixType::SB;
+   list[10] = MatrixType::Id;
+   list[11] = MatrixType::Sk;
+
+   cout << ">=    ";
+   int i;
+   for (i = 0; i<MatrixType::nTypes(); i++)
+      cout << list[i].Value() << " ";
+   cout << "\n";
+   for (i=0; i<MatrixType::nTypes(); i++)
+   {
+      cout << list[i].Value() << " ";
+      for (int j=0; j<MatrixType::nTypes(); j++)
+	 cout << ((list[j]>=list[i]) ? "Yes   " : "No    ");
+      cout << "\n";
+   }
+   cout << "\n";
+}
+
+
+//************** elapsed time class ****************
+
+time_lapse::time_lapse()
+{
+   start_time = ((double)clock())/(double)CLOCKS_PER_SEC;
+}
+
+time_lapse::~time_lapse()
+{
+   double time = ((double)clock())/(double)CLOCKS_PER_SEC - start_time;
+   cout << "Elapsed (processor) time = " << setprecision(2) << time << " seconds" << endl;
+   cout << endl;
+}
+
+
+
+
+
+
+
Index: Shared/newmat/extra/tmt.h
===================================================================
RCS file: Shared/newmat/extra/tmt.h
diff -N Shared/newmat/extra/tmt.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt.h	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,90 @@
+// definition file for test programs
+
+//#define DONT_DO_NRIC         // activate if running a bounds checker
+
+#ifdef use_namespace
+//using namespace NEWMAT;
+namespace NEWMAT {
+#endif
+
+// print time between construction and destruction
+class time_lapse
+{
+   double start_time;
+public:
+   time_lapse();
+   ~time_lapse();
+};
+
+// random number generator
+
+class MultWithCarry
+{
+   unsigned long x;
+   unsigned long crry;
+
+   void NextValue();
+
+   void operator=(const MultWithCarry&) {}    // private so can't access
+
+public:
+   MultWithCarry(double s=0.46875);
+   Real Next();
+   ~MultWithCarry() {}
+};
+
+// fill a matrix with values from the MultWithCarry random number generator
+void FillWithValues(MultWithCarry& MWC, Matrix& M);   
+
+
+void Print(const Matrix& X);
+void Print(const UpperTriangularMatrix& X);
+void Print(const DiagonalMatrix& X);
+void Print(const SymmetricMatrix& X);
+void Print(const LowerTriangularMatrix& X);
+
+void Clean(Matrix&, Real);
+void Clean(DiagonalMatrix&, Real);
+
+#ifdef use_namespace
+}
+using namespace NEWMAT;
+#endif
+
+
+
+void trymat1(); void trymat2(); void trymat3();
+void trymat4(); void trymat5(); void trymat6();
+void trymat7(); void trymat8(); void trymat9();
+void trymata(); void trymatb(); void trymatc();
+void trymatd(); void trymate(); void trymatf();
+void trymatg(); void trymath(); void trymati();
+void trymatj(); void trymatk(); void trymatl();
+void trymatm();
+
+
+
+// body file: tmt.cpp
+// body file: tmt1.cpp
+// body file: tmt2.cpp
+// body file: tmt3.cpp
+// body file: tmt4.cpp
+// body file: tmt5.cpp
+// body file: tmt6.cpp
+// body file: tmt7.cpp
+// body file: tmt8.cpp
+// body file: tmt9.cpp
+// body file: tmta.cpp
+// body file: tmtb.cpp
+// body file: tmtc.cpp
+// body file: tmtd.cpp
+// body file: tmte.cpp
+// body file: tmtf.cpp
+// body file: tmtg.cpp
+// body file: tmth.cpp
+// body file: tmti.cpp
+// body file: tmtj.cpp
+// body file: tmtk.cpp
+// body file: tmtl.cpp
+// body file: tmtm.cpp
+
Index: Shared/newmat/extra/tmt.txt
===================================================================
RCS file: Shared/newmat/extra/tmt.txt
diff -N Shared/newmat/extra/tmt.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt.txt	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,5695 @@
+
+Begin test
+Now print a real number: 3.14159
+
+Matrix type: Rect  (1, 8)
+
+0	0	0	0	0	0	0	1	
+
++     UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    UT    Squ   Rect  Squ   Squ   UT    Squ   UT    Squ   Squ   UT    Squ   
+LT    Squ   LT    Rect  Squ   Squ   LT    Squ   Squ   LT    Squ   LT    Squ   
+Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Squ   Squ   Squ   Rect  Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   
+Sym   Squ   Squ   Rect  Squ   Sym   Sym   Squ   Squ   Squ   Sym   Sym   Squ   
+Diag  UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Diag  Squ   
+Band  Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Squ   
+UpBnd UT    Squ   Rect  Squ   Squ   UpBnd Band  UpBnd Band  Band  UpBnd Squ   
+LwBnd Squ   LT    Rect  Squ   Squ   LwBnd Band  Band  LwBnd Band  LwBnd Squ   
+SmBnd Squ   Squ   Rect  Squ   Sym   SmBnd Band  Band  Band  SmBnd SmBnd Squ   
+Ident UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Squ   
+Skew  Squ   Squ   Rect  Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   Skew  
+
+*     UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    UT    Squ   Rect  Squ   Squ   UT    Squ   UT    Squ   Squ   UT    Squ   
+LT    Squ   LT    Rect  Squ   Squ   LT    Squ   Squ   LT    Squ   LT    Squ   
+Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Squ   Squ   Squ   Rect  Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   
+Sym   Squ   Squ   Rect  Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   
+Diag  UT    LT    Rect  Squ   Squ   Diag  Band  UpBnd LwBnd Band  Diag  Squ   
+Band  Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Squ   
+UpBnd UT    Squ   Rect  Squ   Squ   UpBnd Band  UpBnd Band  Band  UpBnd Squ   
+LwBnd Squ   LT    Rect  Squ   Squ   LwBnd Band  Band  LwBnd Band  LwBnd Squ   
+SmBnd Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Squ   
+Ident UT    LT    Rect  Squ   Squ   Diag  Band  UpBnd LwBnd Band  Ident Squ   
+Skew  Squ   Squ   Rect  Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   Squ   
+
+|     UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+LT    Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Squ   Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Sym   Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Diag  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Band  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+UpBnd Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+LwBnd Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+SmBnd Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Ident Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Skew  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+
+SP    UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    UT    Diag  UT    UT    UT    Diag  UpBnd UpBnd Diag  UpBnd Diag  UT    
+LT    Diag  LT    LT    LT    LT    Diag  LwBnd Diag  LwBnd LwBnd Diag  LT    
+Rect  UT    LT    Rect  Squ   Squ   Diag  Band  UpBnd LwBnd Band  Diag  Squ   
+Squ   UT    LT    Squ   Squ   Squ   Diag  Band  UpBnd LwBnd Band  Diag  Squ   
+Sym   UT    LT    Squ   Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Diag  Skew  
+Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  ????? 
+Band  UpBnd LwBnd Band  Band  Band  Diag  Band  UpBnd LwBnd Band  Diag  Band  
+UpBnd UpBnd Diag  UpBnd UpBnd UpBnd Diag  UpBnd UpBnd Diag  UpBnd Diag  UpBnd 
+LwBnd Diag  LwBnd LwBnd LwBnd LwBnd Diag  LwBnd Diag  LwBnd LwBnd Diag  LwBnd 
+SmBnd UpBnd LwBnd Band  Band  SmBnd Diag  Band  UpBnd LwBnd SmBnd Diag  ????? 
+Ident Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Diag  Ident ????? 
+Skew  UT    LT    Squ   Squ   Skew  ????? Band  UpBnd LwBnd ????? ????? Sym   
+
+KP    UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    UT    Squ   Rect  Squ   Squ   UpBnd Band  UpBnd Band  Band  UpBnd Squ   
+LT    Squ   LT    Rect  Squ   Squ   LwBnd Band  Band  LwBnd Band  LwBnd Squ   
+Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  Rect  
+Squ   Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Squ   
+Sym   Squ   Squ   Rect  Squ   Sym   SmBnd Band  Band  Band  SmBnd SmBnd Squ   
+Diag  UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Diag  Squ   
+Band  Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Squ   
+UpBnd UT    Squ   Rect  Squ   Squ   UpBnd Band  UpBnd Band  Band  UpBnd Squ   
+LwBnd Squ   LT    Rect  Squ   Squ   LwBnd Band  Band  LwBnd Band  LwBnd Squ   
+SmBnd Squ   Squ   Rect  Squ   Sym   SmBnd Band  Band  Band  SmBnd SmBnd Squ   
+Ident UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Diag  Squ   
+Skew  Squ   Squ   Rect  Squ   Squ   Band  Band  Band  Band  Band  Band  Skew  
+
+>=    UT    LT    Rect  Squ   Sym   Diag  Band  UpBnd LwBnd SmBnd Ident Skew  
+UT    Yes   No    Yes   Yes   No    No    No    No    No    No    No    No    
+LT    No    Yes   Yes   Yes   No    No    No    No    No    No    No    No    
+Rect  No    No    Yes   Yes   No    No    No    No    No    No    No    No    
+Squ   No    No    Yes   Yes   No    No    No    No    No    No    No    No    
+Sym   No    No    Yes   Yes   Yes   No    No    No    No    No    No    No    
+Diag  Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   No    No    
+Band  No    No    Yes   Yes   No    No    Yes   No    No    No    No    No    
+UpBnd Yes   No    Yes   Yes   No    No    Yes   Yes   No    No    No    No    
+LwBnd No    Yes   Yes   Yes   No    No    Yes   No    Yes   No    No    No    
+SmBnd No    No    Yes   Yes   Yes   No    Yes   No    No    Yes   No    No    
+Ident Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   Yes   No    
+Skew  No    No    Yes   Yes   No    No    No    No    No    No    No    Yes   
+
+
+  * First test of Matrix package
+  * Matrix test program
+
+Matrix type: LT    (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: UT    (9, 9)
+
+All elements are zero
+
+Matrix type: Rect  (9, 9)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 8)
+
+All elements are zero
+
+Matrix type: Rect  (20, 6)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 20)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+  * Second test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (8, 10)
+
+All elements are zero
+
+Matrix type: Rect  (8, 10)
+
+All elements are zero
+
+Matrix type: Rect  (8, 10)
+
+All elements are zero
+
+Matrix type: Rect  (8, 10)
+
+All elements are zero
+
+Matrix type: Rect  (8, 10)
+
+All elements are zero
+
+Matrix type: Rect  (100, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (20, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 7)
+
+All elements are zero
+
+Matrix type: Rect  (4, 7)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (10, 20)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (0, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 0)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (14, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (4, 6)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (2, 3)
+
+All elements are zero
+
+  * Third test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (6, 7)
+
+All elements are zero
+
+Matrix type: Rect  (6, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (6, 6)
+
+All elements are zero
+
+Matrix type: Diag  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (4, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+  * Fourth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (3, 10)
+
+All elements are zero
+
+Matrix type: Rect  (3, 10)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 8)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Diag  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Diag  (4, 4)
+
+All elements are zero
+
+Matrix type: Diag  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (5, 6)
+
+All elements are zero
+
+Matrix type: Rect  (3, 4)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (5, 6)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: UT    (0, 0)
+
+All elements are zero
+
+Matrix type: UT    (20, 20)
+
+All elements are zero
+
+Matrix type: LT    (0, 0)
+
+All elements are zero
+
+Matrix type: LT    (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (0, 0)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (0, 0)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (1, 0)
+
+All elements are zero
+
+Matrix type: Rect  (1, 20)
+
+All elements are zero
+
+Matrix type: Rect  (0, 1)
+
+All elements are zero
+
+Matrix type: Rect  (20, 1)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+  * Fifth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 6)
+
+All elements are zero
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Rect  (2, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (5, 6)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Rect  (31, 31)
+
+All elements are zero
+
+Matrix type: Diag  (31, 31)
+
+All elements are zero
+
+  * Sixth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: LT    (5, 5)
+
+All elements are zero
+
+Matrix type: LT    (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 10)
+
+All elements are zero
+
+Matrix type: Rect  (5, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 17)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 18)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 99)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 100)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+Matrix type: Rect  (1, 101)
+
+All elements are zero
+
+  * Seventh test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 121)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (11, 11)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 15)
+
+All elements are zero
+
+Matrix type: Rect  (11, 8)
+
+All elements are zero
+
+  * Eighth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Diag  (6, 6)
+
+All elements are zero
+
+Matrix type: Diag  (6, 6)
+
+All elements are zero
+
+Matrix type: Diag  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: LT    (4, 4)
+
+All elements are zero
+
+Matrix type: UT    (4, 4)
+
+All elements are zero
+
+Matrix type: Diag  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (10, 6)
+
+All elements are zero
+
+Matrix type: Rect  (5, 9)
+
+All elements are zero
+
+Matrix type: Rect  (3, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (6, 0)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+  * Ninth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 3)
+
+All elements are zero
+
+Matrix type: Rect  (7, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (18, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (22, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+  * Tenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (8, 6)
+
+All elements are zero
+
+Matrix type: Rect  (8, 6)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (4, 2)
+
+All elements are zero
+
+Matrix type: Rect  (4, 2)
+
+All elements are zero
+
+Matrix type: Rect  (4, 2)
+
+All elements are zero
+
+Matrix type: UT    (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 2)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+  * Eleventh test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 10)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (3, 4)
+
+All elements are zero
+
+Matrix type: Rect  (6, 4)
+
+All elements are zero
+
+Matrix type: Rect  (7, 6)
+
+All elements are zero
+
+Matrix type: Rect  (3, 4)
+
+All elements are zero
+
+Matrix type: Rect  (2, 3)
+
+All elements are zero
+
+  * Twelfth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (15, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 5)
+
+All elements are zero
+
+Matrix type: Rect  (15, 1)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 5)
+
+All elements are zero
+
+Matrix type: Rect  (7, 5)
+
+All elements are zero
+
+Matrix type: Rect  (7, 5)
+
+All elements are zero
+
+Matrix type: UT    (20, 20)
+
+All elements are zero
+
+Matrix type: UT    (5, 5)
+
+All elements are zero
+
+Matrix type: UT    (20, 20)
+
+All elements are zero
+
+Matrix type: UT    (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: UT    (20, 20)
+
+All elements are zero
+
+Matrix type: LT    (20, 20)
+
+All elements are zero
+
+Matrix type: LT    (5, 5)
+
+All elements are zero
+
+Matrix type: LT    (20, 20)
+
+All elements are zero
+
+Matrix type: LT    (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 8)
+
+All elements are zero
+
+Matrix type: LT    (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 30)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 30)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 30)
+
+All elements are zero
+
+Matrix type: Rect  (0, 0)
+
+All elements are zero
+
+Matrix type: Rect  (20, 60)
+
+All elements are zero
+
+  * Thirteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (20, 5)
+
+All elements are zero
+
+Matrix type: Rect  (20, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 3)
+
+All elements are zero
+
+Matrix type: Rect  (3, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 7)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (40, 40)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (50, 50)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+  * Fourteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (8, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (21, 20)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Rect  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Rect  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (21, 21)
+
+All elements are zero
+
+Matrix type: Diag  (30, 30)
+
+All elements are zero
+
+Matrix type: Rect  (30, 30)
+
+All elements are zero
+
+Matrix type: Rect  (30, 30)
+
+All elements are zero
+
+Matrix type: Rect  (30, 30)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Diag  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Diag  (2, 2)
+
+All elements are zero
+
+Matrix type: Diag  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Diag  (2, 2)
+
+All elements are zero
+
+Matrix type: Diag  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (22, 20)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Sym   (10, 10)
+
+All elements are zero
+
+Matrix type: Diag  (9, 9)
+
+All elements are zero
+
+Matrix type: Diag  (9, 9)
+
+All elements are zero
+
+Matrix type: Diag  (9, 9)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Diag  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Diag  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+  * Fifteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2187, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2187, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2310, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2310, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2401, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2401, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2197, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2197, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2021, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2021, 1)
+
+All elements are zero
+
+Matrix type: Rect  (768, 1)
+
+All elements are zero
+
+Matrix type: Rect  (768, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1280, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1280, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1792, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1792, 1)
+
+All elements are zero
+
+Matrix type: Rect  (320, 1)
+
+All elements are zero
+
+Matrix type: Rect  (320, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (50, 1)
+
+All elements are zero
+
+Matrix type: Rect  (50, 1)
+
+All elements are zero
+
+Matrix type: Rect  (98, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (22, 1)
+
+All elements are zero
+
+Matrix type: Rect  (51, 1)
+
+All elements are zero
+
+Matrix type: Rect  (51, 1)
+
+All elements are zero
+
+Matrix type: Rect  (100, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1025, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1025, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1226, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1226, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2450, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (13, 1)
+
+All elements are zero
+
+Matrix type: Rect  (13, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (9, 1)
+
+All elements are zero
+
+Matrix type: Rect  (9, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (30, 1)
+
+All elements are zero
+
+Matrix type: Rect  (30, 1)
+
+All elements are zero
+
+Matrix type: Rect  (42, 1)
+
+All elements are zero
+
+Matrix type: Rect  (42, 1)
+
+All elements are zero
+
+Matrix type: Rect  (24, 1)
+
+All elements are zero
+
+Matrix type: Rect  (24, 1)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (48, 1)
+
+All elements are zero
+
+Matrix type: Rect  (48, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (26, 1)
+
+All elements are zero
+
+Matrix type: Rect  (26, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (18, 1)
+
+All elements are zero
+
+Matrix type: Rect  (18, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (27, 1)
+
+All elements are zero
+
+Matrix type: Rect  (27, 1)
+
+All elements are zero
+
+Matrix type: Rect  (33, 1)
+
+All elements are zero
+
+Matrix type: Rect  (33, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (1, 16)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 3)
+
+All elements are zero
+
+Matrix type: Rect  (4, 3)
+
+All elements are zero
+
+Matrix type: Rect  (4, 3)
+
+All elements are zero
+
+Matrix type: Rect  (4, 3)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (4, 5)
+
+All elements are zero
+
+Matrix type: Rect  (5, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 3)
+
+All elements are zero
+
+Matrix type: Rect  (5, 3)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2187, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2187, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2310, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2310, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2401, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2401, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2197, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2197, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2021, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2021, 1)
+
+All elements are zero
+
+Matrix type: Rect  (768, 1)
+
+All elements are zero
+
+Matrix type: Rect  (768, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1280, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1280, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1792, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1792, 1)
+
+All elements are zero
+
+Matrix type: Rect  (320, 1)
+
+All elements are zero
+
+Matrix type: Rect  (320, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (50, 1)
+
+All elements are zero
+
+Matrix type: Rect  (50, 1)
+
+All elements are zero
+
+Matrix type: Rect  (98, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (22, 1)
+
+All elements are zero
+
+Matrix type: Rect  (51, 1)
+
+All elements are zero
+
+Matrix type: Rect  (51, 1)
+
+All elements are zero
+
+Matrix type: Rect  (100, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1025, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1025, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2048, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1226, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1226, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2450, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (13, 1)
+
+All elements are zero
+
+Matrix type: Rect  (13, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (12, 1)
+
+All elements are zero
+
+Matrix type: Rect  (9, 1)
+
+All elements are zero
+
+Matrix type: Rect  (9, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (16, 1)
+
+All elements are zero
+
+Matrix type: Rect  (30, 1)
+
+All elements are zero
+
+Matrix type: Rect  (30, 1)
+
+All elements are zero
+
+Matrix type: Rect  (42, 1)
+
+All elements are zero
+
+Matrix type: Rect  (42, 1)
+
+All elements are zero
+
+Matrix type: Rect  (24, 1)
+
+All elements are zero
+
+Matrix type: Rect  (24, 1)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (40, 1)
+
+All elements are zero
+
+Matrix type: Rect  (48, 1)
+
+All elements are zero
+
+Matrix type: Rect  (48, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 1)
+
+All elements are zero
+
+Matrix type: Rect  (4, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (5, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (26, 1)
+
+All elements are zero
+
+Matrix type: Rect  (26, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (32, 1)
+
+All elements are zero
+
+Matrix type: Rect  (18, 1)
+
+All elements are zero
+
+Matrix type: Rect  (18, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (202, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1000, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (275, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1001, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (3, 1)
+
+All elements are zero
+
+Matrix type: Rect  (27, 1)
+
+All elements are zero
+
+Matrix type: Rect  (27, 1)
+
+All elements are zero
+
+Matrix type: Rect  (33, 1)
+
+All elements are zero
+
+Matrix type: Rect  (33, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 1)
+
+All elements are zero
+
+  * Sixteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (1, 7)
+
+All elements are zero
+
+Matrix type: Rect  (1, 6)
+
+All elements are zero
+
+Matrix type: Rect  (1, 6)
+
+All elements are zero
+
+Matrix type: Rect  (1, 8)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 5)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+  * Seventeenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (6, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 7)
+
+All elements are zero
+
+Matrix type: Rect  (80, 1)
+
+All elements are zero
+
+Matrix type: Rect  (80, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (80, 1)
+
+All elements are zero
+
+Matrix type: Rect  (80, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 8)
+
+All elements are zero
+
+Matrix type: Rect  (8, 1)
+
+All elements are zero
+
+Matrix type: Rect  (7, 1)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (7, 2)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Sym   (20, 20)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (10, 10)
+
+All elements are zero
+
+Matrix type: Rect  (6, 6)
+
+All elements are zero
+
+Matrix type: Rect  (9, 2)
+
+All elements are zero
+
+Matrix type: Rect  (1, 1)
+
+All elements are zero
+
+Matrix type: Rect  (20, 30)
+
+All elements are zero
+
+Matrix type: UT    (25, 25)
+
+All elements are zero
+
+Matrix type: LT    (25, 25)
+
+All elements are zero
+
+Matrix type: Diag  (25, 25)
+
+All elements are zero
+
+Matrix type: Sym   (25, 25)
+
+All elements are zero
+
+Matrix type: Diag  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (10, 1)
+
+All elements are zero
+
+Matrix type: Rect  (1, 10)
+
+All elements are zero
+
+Matrix type: Rect  (5, 5)
+
+All elements are zero
+
+Matrix type: Diag  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (4, 4)
+
+All elements are zero
+
+Matrix type: Rect  (1, 2)
+
+All elements are zero
+
+  * Eighteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (23, 1)
+
+All elements are zero
+
+Matrix type: Rect  (10, 20)
+
+All elements are zero
+
+  * Nineteenth test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (13, 7)
+
+All elements are zero
+
+Matrix type: Rect  (13, 7)
+
+All elements are zero
+
+Matrix type: Rect  (13, 7)
+
+All elements are zero
+
+Matrix type: Rect  (13, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: Diag  (7, 7)
+
+All elements are zero
+
+Matrix type: LT    (7, 7)
+
+All elements are zero
+
+Matrix type: LT    (7, 7)
+
+All elements are zero
+
+Matrix type: LT    (7, 7)
+
+All elements are zero
+
+Matrix type: LT    (7, 7)
+
+All elements are zero
+
+Matrix type: UT    (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (25, 25)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (19, 19)
+
+All elements are zero
+
+Matrix type: Rect  (2, 1)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+Matrix type: Rect  (7, 7)
+
+All elements are zero
+
+  * Twentieth test of Matrix package
+  * Matrix test program
+C subscripts not enabled, not tested
+
+
+  * Twenty first test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (1, 28)
+
+All elements are zero
+
+  * Twenty second test of Matrix package
+  * Matrix test program
+
+Matrix type: Rect  (8, 9)
+
+All elements are zero
+
+Matrix type: Diag  (150, 150)
+
+All elements are zero
+
+Matrix type: UT    (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: UT    (12, 12)
+
+All elements are zero
+
+Matrix type: LT    (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: UT    (12, 12)
+
+All elements are zero
+
+Matrix type: LT    (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (24, 24)
+
+All elements are zero
+
+Matrix type: Rect  (24, 24)
+
+All elements are zero
+
+Matrix type: Rect  (24, 24)
+
+All elements are zero
+
+Matrix type: Rect  (1, 4)
+
+All elements are zero
+
+Matrix type: UT    (24, 24)
+
+All elements are zero
+
+Matrix type: LT    (24, 24)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (12, 12)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Rect  (1, 15)
+
+All elements are zero
+
+Matrix type: Rect  (15, 1)
+
+All elements are zero
+
+Matrix type: Rect  (15, 15)
+
+All elements are zero
+
+Matrix type: Rect  (3, 12)
+
+All elements are zero
+
+Matrix type: Rect  (2, 2)
+
+All elements are zero
+
+Matrix type: Rect  (3, 3)
+
+All elements are zero
+
+Matrix type: Squ   (5, 5)
+
+All elements are zero
+
+Matrix type: Squ   (4, 4)
+
+All elements are zero
+
+Matrix type: Squ   (4, 4)
+
+All elements are zero
+
+End of tests
+
+(The following memory checks are probably not valid with all
+compilers - see documentation)
+
+Checking for lost memory: 8862788 8862788  - ok
+
+
+Checking for lost memory: 8862788 8862788  - ok
+
+Elapsed (processor) time = 1.1 seconds
+
+Number of matrices tested                 = 1381
+Number of non-zero matrices (should be 1) = 1
Index: Shared/newmat/extra/tmt1.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt1.cpp
diff -N Shared/newmat/extra/tmt1.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt1.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,284 @@
+
+#define WANT_STREAM
+
+
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+void trymat1()
+{
+//   cout << "\nFirst test of Matrix package\n\n";
+   Tracer et("First test of Matrix package");
+   Tracer::PrintTrace();
+   {
+      Tracer et1("Stage 1");
+      int i,j;
+
+      LowerTriangularMatrix L(10);
+      for (i=1;i<=10;i++) for (j=1;j<=i;j++) L(i,j)=2.0+i*i+j;
+      SymmetricMatrix S(10);
+      for (i=1;i<=10;i++) for (j=1;j<=i;j++) S(i,j)=i*j+1.0;
+      SymmetricMatrix S1 = S / 2.0;
+      S = S1 * 2.0;
+      UpperTriangularMatrix U=L.t()*2.0;
+      Print(LowerTriangularMatrix(L-U.t()*0.5));
+      DiagonalMatrix D(10);
+      for (i=1;i<=10;i++) D(i,i)=(i-4)*(i-5)*(i-6);
+      Matrix M=(S+U-D+L)*(L+U-D+S);
+      DiagonalMatrix DD=D*D;
+      LowerTriangularMatrix LD=L*D;
+      // expressions split for Turbo C
+      Matrix M1 = S*L + U*L - D*L + L*L + 10.0;
+      { M1 = M1 + S*U + U*U - D*U + L*U - S*D; }
+      { M1 = M1 - U*D + DD - LD + S*S; }
+      { M1 = M1 + U*S - D*S + L*S - 10.0; }
+      M=M1-M;
+      Print(M);
+   }
+   {
+      Tracer et1("Stage 2");
+      int i,j;
+
+      LowerTriangularMatrix L(9);
+      for (i=1;i<=9;i++) for (j=1;j<=i;j++) L(i,j)=1.0+j;
+      UpperTriangularMatrix U1(9);
+      for (j=1;j<=9;j++) for (i=1;i<=j;i++) U1(i,j)=1.0+i;
+      LowerTriangularMatrix LX(9);
+      for (i=1;i<=9;i++) for (j=1;j<=i;j++) LX(i,j)=1.0+i*i;
+      UpperTriangularMatrix UX(9);
+      for (j=1;j<=9;j++) for (i=1;i<=j;i++) UX(i,j)=1.0+j*j;
+      {
+         L=L+LX/0.5;   L=L-LX*3.0;   L=LX*2.0+L;
+         U1=U1+UX*2.0; U1=U1-UX*3.0; U1=UX*2.0+U1;
+      }
+
+
+      SymmetricMatrix S(9);
+      for (i=1;i<=9;i++) for (j=1;j<=i;j++) S(i,j)=i*i+j;
+      {
+         SymmetricMatrix S1 = S;
+         S=S1+5.0;
+         S=S-3.0;
+      }
+
+      DiagonalMatrix D(9);
+      for (i=1;i<=9;i++) D(i,i)=S(i,i);
+      UpperTriangularMatrix U=L.t()*2.0;
+      {
+         U1=U1*2.0 - U;  Print(U1);
+         L=L*2.0-D; U=U-D;
+      }
+      Matrix M=U+L; S=S*2.0; M=S-M; Print(M);
+   }
+   {
+      Tracer et1("Stage 3");
+      int i,j;
+      Matrix M(10,3), N(10,3);
+      for (i = 1; i<=10; i++) for (j = 1; j<=3; j++)
+         {  M(i,j) = 2*i-j; N(i,j) = i*j + 20; }
+      Matrix MN = M + N, M1;
+
+      M1 = M; M1 += N; M1 -= MN; Print(M1);
+      M1 = M; M1 += M1; M1 = M1 - M * 2; Print(M1);
+      M1 = M; M1 += N * 2; M1 -= (MN + N); Print(M1);
+      M1 = M; M1 -= M1; Print(M1);
+      M1 = M; M1 -= MN + M1; M1 += N + M; Print(M1);
+      M1 = M; M1 -= 5; M1 -= M; M1 *= 0.2; M1 = M1 + 1; Print(M1);
+      Matrix NT = N.t();
+      M1 = M; M1 *= NT; M1 -= M * N.t(); Print(M1);
+      M = M * M.t();
+      DiagonalMatrix D(10); D = 2;
+      M1 = M; M1 += D; M1 -= M; M1 = M1 - D; Print(M1);
+      M1 = M; M1 -= D; M1 -= M; M1 = M1 + D; Print(M1);
+      M1 = M; M1 *= D; M1 /= 2; M1 -= M; Print(M1);
+      SymmetricMatrix SM; SM << M;
+      // UpperTriangularMatrix SM; SM << M;
+      SM += 10; M1 = SM - M; M1 /=10; M1 = M1 - 1; Print(M1);
+   }
+   {
+      Tracer et1("Stage 4");
+      int i,j;
+      Matrix M(10,3), N(10,5);
+      for (i = 1; i<=10; i++) for (j = 1; j<=3; j++) M(i,j) = 2*i-j;
+      for (i = 1; i<=10; i++) for (j = 1; j<=5; j++) N(i,j) = i*j + 20;
+      Matrix M1;
+      M1 = M; M1 |= N; M1 &= N | M;
+      M1 -= (M | N) & (N | M); Print(M1);
+      M1 = M; M1 |= M1; M1 &= M1;
+      M1 -= (M | M) & (M | M); Print(M1);
+
+   }
+   {
+      Tracer et1("Stage 5");
+      int i,j;
+      BandMatrix BM1(10,2,3), BM2(10,4,1); Matrix M1(10,10), M2(10,10);
+      for (i=1;i<=10;i++) for (j=1;j<=10;j++)
+        { M1(i,j) = 0.5*i+j*j-50; M2(i,j) = (i*101 + j*103) % 13; }
+      BM1.Inject(M1); BM2.Inject(M2);
+      BandMatrix BM = BM1; BM += BM2;
+      Matrix M1X = BM1; Matrix M2X = BM2; Matrix MX = BM;
+      MX -= M1X + M2X; Print(MX);
+      MX = BM1; MX += BM2; MX -= M1X; MX -= M2X; Print(MX);
+      SymmetricBandMatrix SM1; SM1 << BM1 * BM1.t(); 
+      SymmetricBandMatrix SM2; SM2 << BM2 * BM2.t();
+      SM1 *= 5.5;
+      M1X *= M1X.t(); M1X *= 5.5; M2X *= M2X.t();
+      SM1 -= SM2; M1 = SM1 - M1X + M2X; Print(M1);
+      M1 = BM1; BM1 *= SM1; M1 = M1 * SM1 - BM1; Print(M1); 
+      M1 = BM1; BM1 -= SM1; M1 = M1 - SM1 - BM1; Print(M1); 
+      M1 = BM1; BM1 += SM1; M1 = M1 + SM1 - BM1; Print(M1); 
+      
+   }
+   {
+      Tracer et1("Stage 6");
+      int i,j;
+      Matrix M(10,10), N(10,10);
+      for (i = 1; i<=10; i++) for (j = 1; j<=10; j++)
+         {  M(i,j) = 2*i-j; N(i,j) = i*j + 20; }
+      GenericMatrix GM = M;
+      GM += N; Matrix M1 = GM - N - M; Print(M1);
+      DiagonalMatrix D(10); D = 3;
+      GM = D; GM += N; GM += M; GM += D;
+      M1 = D*2 - GM + M + N; Print(M1);
+      GM = D; GM *= 4; GM += 16; GM /= 8; GM -= 2;
+      GM -= D / 2; M1 = GM; Print(M1);
+      GM = D; GM *= M; GM *= N; GM /= 3; M1 = M*N - GM; Print(M1);
+      GM = D; GM |= M; GM &= N | D; M1 = GM - ((D | M) & (N | D));
+      Print(M1);
+      GM = M; M1 = M; GM += 5; GM *= 3; M *= 3; M += 15; M1 = GM - M;
+      Print(M1);
+      D.ReSize(10); for (i = 1; i<=10; i++) D(i) = i;
+      M1 = D + 10; GM = D; GM += 10; M1 -= GM; Print(M1);
+      GM = M; GM -= D; M1 = GM; GM = D; GM -= M; M1 += GM; Print(M1);
+      GM = M; GM *= D; M1 = GM; GM = D; GM *= M.t();
+      M1 -= GM.t(); Print(M1);
+      GM = M; GM += 2 * GM; GM -= 3 * M; M1 = GM; Print(M1);
+      GM = M; GM |= GM; GM -= (M | M); M1 = GM; Print(M1);
+      GM = M; GM &= GM; GM -= (M & M); M1 = GM; Print(M1);
+      M1 = M; M1 = (M1.t() & M.t()) - (M | M).t(); Print(M1);
+      M1 = M; M1 = (M1.t() | M.t()) - (M & M).t(); Print(M1);
+
+   }
+
+   {
+      Tracer et1("Stage 7");
+      // test for bug in MS VC5
+      int n = 3;
+      int k; int j;
+      Matrix A(n,n), B(n,n);
+
+      //first version - MS VC++ 5 mis-compiles if optimisation is on
+      for (k=1; k<=n; k++)
+      {
+         for (j = 1; j <= n; j++) A(k,j) = ((k-1) * (2*j-1));
+      }
+
+      //second version
+      for (k=1; k<=n; k++)
+      {
+         const int k1 = k-1;          // otherwise Visual C++ 5 fails
+         for (j = 1; j <= n; j++) B(k,j) = (k1 * (2*j-1));
+      }
+
+      if (A != B)
+      {
+         cout << "\nVisual C++ version 5 compiler error?";
+         cout << "\nTurn off optimisation";
+      }
+
+      A -= B; Print(A);
+
+   }
+
+   {
+      Tracer et1("Stage 8");
+      // Cross product
+      ColumnVector i(3); i << 1 << 0 << 0;
+      ColumnVector j(3); j << 0 << 1 << 0;
+      ColumnVector k(3); k << 0 << 0 << 1;
+      ColumnVector X;
+      X = CrossProduct(i,j) - k; Print(X);
+      X = CrossProduct(j,k) - i; Print(X);
+      X = CrossProduct(k,i) - j; Print(X);
+      X = CrossProduct(j,i) + k; Print(X);
+      X = CrossProduct(k,j) + i; Print(X);
+      X = CrossProduct(i,k) + j; Print(X);
+      X = CrossProduct(i,i); Print(X);
+      X = CrossProduct(j,j); Print(X);
+      X = CrossProduct(k,k); Print(X);
+
+      ColumnVector A(3); A << 2.25 << 1.75 << -7.5;
+      ColumnVector B(3); B << -0.5 << 4.75 << 3.25;
+      ColumnVector C(3); C << 9.25 << 3.5  << 1.25;
+
+      Real d0 = (A | B | C).Determinant();    // Vector triple product
+      Real d1 = DotProduct(CrossProduct(A, B), C);
+      Real d2 = DotProduct(CrossProduct(B, C), A);
+      Real d3 = DotProduct(CrossProduct(C, A), B);
+      X << (d1 - d0) << (d2 - d0) << (d3 - d0);
+      Clean(X, 0.000000001); Print(X);
+
+      X = CrossProduct(A, CrossProduct(B, C))
+        + CrossProduct(B, CrossProduct(C, A))
+        + CrossProduct(C, CrossProduct(A, B));
+      Print(X);
+
+      RowVector XT = CrossProduct(A.AsRow(), B.AsRow());
+      XT -= CrossProduct(A, B).AsRow();
+      Print(XT);
+   }
+
+   {
+      Tracer et1("Stage 9");
+      // More cross product
+      int i, j;
+      Matrix M(10,3), N(10,3);
+      for (i = 1; i<=10; i++) for (j = 1; j<=3; j++)
+         {  M(i,j) = 2*i-j; N(i,j) = i*j + 20; }
+
+      Matrix CP1 = CrossProductRows(M, N);
+      Matrix CP2(10,3);
+      for (i = 1; i<=10; i++)
+         CP2.Row(i) = CrossProduct(M.Row(i), N.Row(i));
+      CP2 -= CP1; Print(CP2);
+
+      CP2 = CrossProductColumns(M.t(), N.t());
+      CP2 -= CP1.t(); Print(CP2);
+   }
+
+   {
+      Tracer et1("Stage 10");
+      // Make sure RNG works
+      MultWithCarry mwc;
+      ColumnVector cv(10);
+      for (int i = 1; i <= 10; ++i) cv(i) = mwc.Next();
+      cv *= 100.0;
+      cv(1) -= 6.27874;	
+      cv(2) -= 42.1718;	
+      cv(3) -= 80.2854;	
+      cv(4) -= 12.961;	
+      cv(5) -= 17.7499;	
+      cv(6) -= 13.2657;	
+      cv(7) -= 50.4923;	
+      cv(8) -= 26.095;	
+      cv(9) -= 57.9147;	
+      cv(10) -= 30.1778;	
+      Clean(cv, 0.0001); Print(cv);
+   }
+
+
+//   cout << "\nEnd of first test\n";
+}
+
Index: Shared/newmat/extra/tmt2.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt2.cpp
diff -N Shared/newmat/extra/tmt2.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt2.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,299 @@
+
+//#define WANT_STREAM
+
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+void trymat2()
+{
+//   cout << "\nSecond test of Matrix package\n\n";
+   Tracer et("Second test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i,j;
+
+   Matrix M(3,5);
+   for (i=1; i<=3; i++) for (j=1; j<=5; j++) M(i,j) = 100*i + j;
+   Matrix X(8,10);
+   for (i=1; i<=8; i++) for (j=1; j<=10; j++) X(i,j) = 1000*i + 10*j;
+   Matrix Y = X; Matrix Z = X;
+   { X.SubMatrix(2,4,3,7) << M; }
+   for (i=1; i<=3; i++) for (j=1; j<=5; j++) Y(i+1,j+2) = 100*i + j;
+   Print(Matrix(X-Y));
+
+
+   Real a[15]; Real* r = a;
+   for (i=1; i<=3; i++) for (j=1; j<=5; j++) *r++ = 100*i + j;
+   { Z.SubMatrix(2,4,3,7) << a; }
+   Print(Matrix(Z-Y));
+
+   { M=33; X.SubMatrix(2,4,3,7) << M; }
+   { Z.SubMatrix(2,4,3,7) = 33; }
+   Print(Matrix(Z-X));
+
+   for (i=1; i<=8; i++) for (j=1; j<=10; j++) X(i,j) = 1000*i + 10*j;
+   Y = X;
+   UpperTriangularMatrix U(5);
+   for (i=1; i<=5; i++) for (j=i; j<=5; j++) U(i,j) = 100*i + j;
+   { X.SubMatrix(3,7,5,9) << U; }
+   for (i=1; i<=5; i++) for (j=i; j<=5; j++) Y(i+2,j+4) = 100*i + j;
+   for (i=1; i<=5; i++) for (j=1; j<i; j++) Y(i+2,j+4) = 0.0;
+   Print(Matrix(X-Y));
+   for (i=1; i<=8; i++) for (j=1; j<=10; j++) X(i,j) = 1000*i + 10*j;
+   Y = X;
+   for (i=1; i<=5; i++) for (j=i; j<=5; j++) U(i,j) = 100*i + j;
+   { X.SubMatrix(3,7,5,9).Inject(U); }
+   for (i=1; i<=5; i++) for (j=i; j<=5; j++) Y(i+2,j+4) = 100*i + j;
+   Print(Matrix(X-Y));
+
+
+   // test growing and shrinking a vector
+   {
+      ColumnVector V(100);
+      for (i=1;i<=100;i++) V(i) = i*i+i;
+      V = V.Rows(1,50);               // to get first 50 vlaues.
+
+      {
+         V.Release(); ColumnVector VX=V;
+         V.ReSize(100); V = 0.0; V.Rows(1,50)=VX;
+      }                               // V now length 100
+
+      M=V; M=100;                     // to make sure V will hold its values
+      for (i=1;i<=50;i++) V(i) -= i*i+i;
+      Print(V);
+
+
+	   // test redimensioning vectors with two dimensions given
+      ColumnVector CV1(10); CV1 = 10;
+      ColumnVector CV2(5); CV2.ReSize(10,1); CV2 = 10;
+      V = CV1-CV2; Print(V);
+
+      RowVector RV1(20); RV1 = 100;
+      RowVector RV2; RV2.ReSize(1,20); RV2 = 100;
+      V = (RV1-RV2).t(); Print(V);
+
+      X.ReSize(4,7);
+      for (i=1; i<=4; i++) for (j=1; j<=7; j++) X(i,j) = 1000*i + 10*j;
+      Y = 10.5 * X;
+      Z = 7.25 - Y;
+      M = Z + X * 10.5 - 7.25;
+      Print(M);
+      Y = 2.5 * X;
+      Z = 9.25 + Y;
+      M = Z - X * 2.5 - 9.25;
+      Print(M);
+      U.ReSize(8);
+      for (i=1; i<=8; i++) for (j=i; j<=8; j++) U(i,j) = 100*i + j;
+      Y = 100 - U;
+      M = Y + U - 100;
+      Print(M);
+   }
+
+   {
+      SymmetricMatrix S,T;
+
+      S << (U + U.t());
+      T = 100 - S; M = T + S - 100; Print(M);
+      T = 100 - 2 * S; M = T + S * 2 - 100; Print(M);
+      X = 100 - 2 * S; M = X + S * 2 - 100; Print(M);
+      T = S; T = 100 - T; M = T + S - 100; Print(M);
+   }
+
+   // test new
+   {
+      ColumnVector CV1; RowVector RV1;
+      Matrix* MX; MX = new Matrix; if (!MX) Throw(Bad_alloc("New fails "));
+      MX->ReSize(10,20);
+      for (i = 1; i <= 10; i++) for (j = 1; j <= 20; j++)
+         (*MX)(i,j) = 100 * i + j;
+      ColumnVector* CV = new ColumnVector(10);
+      if (!CV) Throw(Bad_alloc("New fails "));
+      *CV << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10;
+      RowVector* RV =  new RowVector(CV->t() | (*CV + 10).t());
+      if (!RV) Throw(Bad_alloc("New fails "));
+      CV1 = ColumnVector(10); CV1 = 1; RV1 = RowVector(20); RV1 = 1;
+      *MX -= 100 * *CV * RV1 + CV1 * *RV;
+      Print(*MX);
+      delete MX; delete CV; delete RV;
+   }
+
+
+   // test copying of vectors and matrices with no elements
+   {
+      ColumnVector dims(16);
+      Matrix M1; Matrix M2 = M1; Print(M2);
+      dims(1) = M2.Nrows(); dims(2) = M2.Ncols();
+      dims(3) = (Real)(unsigned long)M2.Store(); dims(4) = M2.Storage();
+      M2 = M1;
+      dims(5) = M2.Nrows(); dims(6) = M2.Ncols();
+      dims(7) = (Real)(unsigned long)M2.Store(); dims(8) = M2.Storage();
+      M2.ReSize(10,20); M2.CleanUp();
+      dims(9) = M2.Nrows(); dims(10) = M2.Ncols();
+      dims(11) = (Real)(unsigned long)M2.Store(); dims(12) = M2.Storage();
+      M2.ReSize(20,10); M2.ReSize(0,0);
+      dims(13) = M2.Nrows(); dims(14) = M2.Ncols();
+      dims(15) = (Real)(unsigned long)M2.Store(); dims(16) = M2.Storage();
+      Print(dims);
+   }
+
+   {
+      ColumnVector dims(16);
+      ColumnVector M1; ColumnVector M2 = M1; Print(M2);
+      dims(1) = M2.Nrows(); dims(2) = M2.Ncols()-1;
+      dims(3) = (Real)(unsigned long)M2.Store(); dims(4) = M2.Storage();
+      M2 = M1;
+      dims(5) = M2.Nrows(); dims(6) = M2.Ncols()-1;
+      dims(7) = (Real)(unsigned long)M2.Store(); dims(8) = M2.Storage();
+      M2.ReSize(10); M2.CleanUp();
+      dims(9) = M2.Nrows(); dims(10) = M2.Ncols()-1;
+      dims(11) = (Real)(unsigned long)M2.Store(); dims(12) = M2.Storage();
+      M2.ReSize(10); M2.ReSize(0);
+      dims(13) = M2.Nrows(); dims(14) = M2.Ncols()-1;
+      dims(15) = (Real)(unsigned long)M2.Store(); dims(16) = M2.Storage();
+      Print(dims);
+   }
+
+   {
+      ColumnVector dims(16);
+      RowVector M1; RowVector M2 = M1; Print(M2);
+      dims(1) = M2.Nrows()-1; dims(2) = M2.Ncols();
+      dims(3) = (Real)(unsigned long)M2.Store(); dims(4) = M2.Storage();
+      M2 = M1;
+      dims(5) = M2.Nrows()-1; dims(6) = M2.Ncols();
+      dims(7) = (Real)(unsigned long)M2.Store(); dims(8) = M2.Storage();
+      M2.ReSize(10); M2.CleanUp();
+      dims(9) = M2.Nrows()-1; dims(10) = M2.Ncols();
+      dims(11) = (Real)(unsigned long)M2.Store(); dims(12) = M2.Storage();
+      M2.ReSize(10); M2.ReSize(0);
+      dims(13) = M2.Nrows()-1; dims(14) = M2.Ncols();
+      dims(15) = (Real)(unsigned long)M2.Store(); dims(16) = M2.Storage();
+      Print(dims);
+   }
+
+   // test identity matrix
+   {
+      Matrix M;
+      IdentityMatrix I(10); DiagonalMatrix D(10); D = 1;
+      M = I; M -= D; Print(M);
+      D -= I; Print(D);
+      ColumnVector X(8);
+      D = 1;
+      X(1) = Sum(D) - Sum(I);
+      X(2) = SumAbsoluteValue(D) - SumAbsoluteValue(I);
+      X(3) = SumSquare(D) - SumSquare(I);
+      X(4) = Trace(D) - Trace(I);
+      X(5) = Maximum(D) - Maximum(I);
+      X(6) = Minimum(D) - Minimum(I);
+      X(7) = LogDeterminant(D).LogValue() - LogDeterminant(I).LogValue();
+      X(8) = LogDeterminant(D).Sign() - LogDeterminant(I).Sign();
+      Clean(X,0.00000001); Print(X);
+
+      for (i = 1; i <= 10; i++) for (j = 1; j <= 10; j++)
+         M(i,j) = 100 * i + j;
+      Matrix N;
+      N = M * I - M; Print(N);
+      N = I * M - M; Print(N);
+      N = M * I.i() - M; Print(N);
+      N = I.i() * M - M; Print(N);
+      N = I.i(); N -= I; Print(N);
+      N = I.t(); N -= I; Print(N);
+      N = I.t(); N += (-I); Print(N); // <----------------
+      D = I; N = D; D = 1; N -= D; Print(N);
+      N = I; D = 1; N -= D; Print(N);
+      N = M + 2 * IdentityMatrix(10); N -= (M + 2 * D); Print(N);
+
+      I *= 4;
+
+      D = 4;
+
+      X.ReSize(14);
+      X(1) = Sum(D) - Sum(I);
+      X(2) = SumAbsoluteValue(D) - SumAbsoluteValue(I);
+      X(3) = SumSquare(D) - SumSquare(I);
+      X(4) = Trace(D) - Trace(I);
+      X(5) = Maximum(D) - Maximum(I);
+      X(6) = Minimum(D) - Minimum(I);
+      X(7) = LogDeterminant(D).LogValue() - LogDeterminant(I).LogValue();  // <--
+      X(8) = LogDeterminant(D).Sign() - LogDeterminant(I).Sign();
+      int i,j;
+      X(9) = I.Maximum1(i) - 4; X(10) = i-1;
+      X(11) = I.Maximum2(i,j) - 4; X(12) = i-10; X(13) = j-10;
+      X(14) = I.Nrows() - 10;
+      Clean(X,0.00000001); Print(X);
+
+
+      N = D.i();
+      N += I / (-16);
+      Print(N);
+      N = M * I - 4 * M; Print(N);
+      N = I * M - 4 * M; Print(N);
+      N = M * I.i() - 0.25 * M; Print(N);
+      N = I.i() * M - 0.25 * M; Print(N);
+      N = I.i(); N -= I * 0.0625; Print(N);
+      N = I.i(); N = N - 0.0625 * I; Print(N);
+      N = I.t(); N -= I; Print(N);
+      D = I * 2; N = D; D = 1; N -= 8 * D; Print(N);
+      N = I * 2; N -= 8 * D; Print(N);
+      N = 0.5 * I + M; N -= M; N -= 2.0 * D; Print(N);
+
+      IdentityMatrix J(10); J = 8;
+      D = 4;
+      DiagonalMatrix E(10); E = 8;
+      N = (I + J) - (D + E); Print(N);
+      N = (5*I + 3*J) - (5*D + 3*E); Print(N);
+      N = (-I + J) - (-D + E); Print(N);
+      N = (I - J) - (D - E); Print(N);
+      N = (I | J) - (D | E); Print(N);
+      N = (I & J) - (D & E); Print(N);
+      N = SP(I,J) - SP(D,E); Print(N);
+      N = D.SubMatrix(2,5,3,8) - I.SubMatrix(2,5,3,8); Print(N);
+
+      N = M; N.Inject(I); D << M; N -= (M + I); N += D; Print(N);
+      D = 4;
+
+      IdentityMatrix K = I.i()*7 - J.t()/4;
+      N = D.i() * 7 - E / 4 - K; Print(N);
+      K = I * J; N = K - D * E; Print(N);
+      N = I * J; N -= D * E; Print(N);
+      K = 5*I - 3*J;
+      N = K - (5*D - 3*E); Print(N);
+      K = I.i(); N = K - 0.0625 * I; Print(N);
+      K = I.t(); N = K - I; Print(N);
+
+
+      K.ReSize(20); D.ReSize(20); D = 1;
+      D -= K; Print(D);
+
+      I.ReSize(3); J.ReSize(3); K = I * J; N = K - I; Print(N);
+      K << D; N = K - D; Print(N);
+   }
+   
+   // test add integer
+   {
+      Matrix X(2,3);
+      X << 5.25 << 7.75 << 1.25
+        << 9.00 << 1.00 << 2.50;
+      Matrix Y = X;
+      X = 10 + X;
+      X += (-10);
+      X -= Y;
+      Print(X);
+   }
+   
+   
+
+
+//   cout << "\nEnd of second test\n";
+}
Index: Shared/newmat/extra/tmt3.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt3.cpp
diff -N Shared/newmat/extra/tmt3.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt3.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,160 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+void trymat3()
+{
+   Tracer et("Third test of Matrix package");
+   Tracer::PrintTrace();
+
+   {
+      Tracer et1("Stage 1");
+      int i,j;
+      SymmetricMatrix S(7);
+      for (i=1;i<=7;i++) for (j=1;j<=i;j++) S(i,j)=i*i+j;
+		S=-S+2.0;
+
+      DiagonalMatrix D(7);
+      for (i=1;i<=7;i++) D(i,i)=S(i,i);
+
+      Matrix M4(7,7); { M4=D+(D+4.0); M4=M4-D*2.0;  M4=M4-4.0; Print(M4); }
+      SymmetricMatrix S2=D; Matrix M2=S2;  { M2=-D+M2; Print(M2); }
+      UpperTriangularMatrix U2=D; { M2=U2; M2=D-M2; Print(M2); }
+      LowerTriangularMatrix L2=D; { M2=L2; M2=D-M2; Print(M2); }
+      M2=D; M2=M2-D; Print(M2);
+      for (i=1;i<=7;i++) for (j=1;j<=i;j++) L2(i,j)=2.0-i*i-j;
+      U2=L2.t(); D=D.t(); S=S.t();
+      M4=(L2-1.0)+(U2+1.0)-D-S; Print(M4);
+      M4=(-L2+1.0)+(-U2-1.0)+D+S; Print(M4);
+   }
+
+   {
+      Tracer et1("Stage 2");
+      int i,j;
+      DiagonalMatrix D(6);
+      for (i=1;i<=6;i++) D(i,i)=i*3.0+i*i+2.0;
+      UpperTriangularMatrix U2(7); LowerTriangularMatrix L2(7);
+      for (i=1;i<=7;i++) for (j=1;j<=i;j++) L2(i,j)=2.0-i*i+j;
+		{ U2=L2.t(); }
+      DiagonalMatrix D1(7); for (i=1;i<=7;i++) D1(i,i)=(i-2)*(i-4);
+      Matrix M2(6,7);
+      for (i=1;i<=6;i++) for (j=1;j<=7;j++) M2(i,j)=2.0+i*j+i*i+2.0*j*j;
+      Matrix MD=D; SymmetricMatrix MD1(1); MD1=D1;
+      Matrix MX=MD*M2*MD1 - D*(M2*D1); Print(MX);
+      MX=MD*M2*MD1 - (D*M2)*D1; Print(MX);
+      {
+         D.ReSize(7); for (i=1;i<=7;i++) D(i,i)=i*3.0+i*i+2.0;
+         LowerTriangularMatrix LD(1); LD=D;
+         UpperTriangularMatrix UD(1); UD=D;
+         M2=U2; M2=LD*M2*MD1 - D*(U2*D1); Print(M2);
+         M2=U2; M2=UD*M2*MD1 - (D*U2)*D1; Print(M2);
+         M2=L2; M2=LD*M2*MD1 - D*(L2*D1); Print(M2);
+         M2=L2; M2=UD*M2*MD1 - (D*L2)*D1; Print(M2);
+      }
+   }
+
+   {
+      Tracer et1("Stage 3");
+      // test inverse * scalar
+      DiagonalMatrix D(6);
+      for (int i=1;i<=6;i++) D(i)=i*i;
+      DiagonalMatrix E = D.i() * 4.0;
+      DiagonalMatrix I(6); I = 1.0;
+      E=D*E-I*4.0; Print(E);
+      E = D.i() / 0.25; E=D*E-I*4.0; Print(E);
+   }
+   {
+      Tracer et1("Stage 4");
+      Matrix sigma(3,3); Matrix sigmaI(3,3);
+      sigma = 0; sigma(1,1) = 1.0; sigma(2,2) = 1.0; sigma(3,3) = 1.0;
+      sigmaI = sigma.i();
+      sigmaI -= sigma;  Clean(sigmaI, 0.000000001); Print(sigmaI);
+   }
+   {
+      Tracer et1("Stage 5");
+      Matrix X(5,5); DiagonalMatrix DM(5);
+      for (int i=1; i<=5; i++) for (int j=1; j<=5; j++)
+         X(i,j) = (23*i+59*j) % 43;
+      DM << 1 << 8 << -7 << 2 << 3;
+      Matrix Y = X.i() * DM; Y = X * Y - DM;
+      Clean(Y, 0.000000001); Print(Y);
+   }
+   {
+      Tracer et1("Stage 6");          // test reverse function
+      ColumnVector CV(10), RCV(10);
+      CV  <<  2 << 7 << 1  << 6 << -3 <<  1 << 8 << -4 << 0 << 17;
+      RCV << 17 << 0 << -4 << 8 << 1  << -3 << 6 <<  1 << 7 << 2;
+      ColumnVector X = CV - RCV.Reverse(); Print(X);
+      RowVector Y = CV.t() - RCV.t().Reverse(); Print(Y);
+      DiagonalMatrix D = CV.AsDiagonal() - RCV.AsDiagonal().Reverse();
+      Print(D);
+      X = CV & CV.Rows(1,9).Reverse();
+      ColumnVector Z(19);
+      Z.Rows(1,10) = RCV.Reverse(); Z.Rows(11,19) = RCV.Rows(2,10);
+      X -= Z; Print(X); Z -= Z.Reverse(); Print(Z);
+      Matrix A(3,3); A << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9;
+      Matrix B(3,3); B << 9 << 8 << 7 << 6 << 5 << 4 << 3 << 2 << 1;
+      Matrix Diff = A - B.Reverse(); Print(Diff);
+      Diff = (-A).Reverse() + B; Print(Diff);
+      UpperTriangularMatrix U;
+      U << A.Reverse(); Diff = U; U << B; Diff -= U; Print(Diff);
+      U << (-A).Reverse(); Diff = U; U << B; Diff += U; Print(Diff);
+   }
+   {
+      Tracer et1("Stage 7");           // test IsSingular function
+      ColumnVector XX(4);
+      Matrix A(3,3);
+      A = 0;
+      CroutMatrix B1 = A;
+      XX(1) = B1.IsSingular() ? 0 : 1;
+      A << 1 << 3 << 6
+        << 7 << 11 << 13
+        << 2 << 4  << 1;
+      CroutMatrix B2(A);
+      XX(2) = B2.IsSingular() ? 1 : 0;
+      BandMatrix C(3,1,1); C.Inject(A);
+      BandLUMatrix B3(C);
+      XX(3) = B3.IsSingular() ? 1 : 0;
+      C = 0;
+      BandLUMatrix B4(C);
+      XX(4) = B4.IsSingular() ? 0 : 1;
+      Print(XX);
+   }
+   {
+      Tracer et1("Stage 8");           // inverse with vector of 0s
+      Matrix A(3,3); Matrix Z(3,3); ColumnVector X(6);
+      A <<  1 <<  3 <<  6
+        <<  7 << 11 << 13
+        <<  2 <<  4 <<  1;
+      Z = 0;
+      Matrix B = (A | Z) & (Z | A);   // 6 * 6 matrix
+      X = 0.0;
+      X = B.i() * X;
+      Print(X);
+      // also check inverse with non-zero Y
+      Matrix Y(3,3);
+      Y << 0.0 << 1.0 << 1.0
+        << 5.0 << 0.0 << 5.0
+        << 3.0 << 3.0 << 0.0;
+      Matrix YY = Y & Y;        // stack Y matrices
+      YY = B.i() * YY;
+      Matrix Y1 = A.i() * Y;
+      YY -= Y1 & Y1; Clean(YY, 0.000000001); Print(YY);
+      Y1 = A * Y1 - Y; Clean(Y1, 0.000000001); Print(Y1);
+   }
+
+
+}
+
Index: Shared/newmat/extra/tmt4.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt4.cpp
diff -N Shared/newmat/extra/tmt4.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt4.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,245 @@
+
+//#define WANT_STREAM
+
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+void trymat4()
+{
+//   cout << "\nFourth test of Matrix package\n";
+   Tracer et("Fourth test of Matrix package");
+   Tracer::PrintTrace();
+
+
+   {
+      Tracer et1("Stage 1");
+      int i, j;
+      Matrix M(10,10);
+      UpperTriangularMatrix U(10);
+      for (i=1;i<=10;i++) for (j=1;j<=10;j++) M(i,j) = 100*i+j;
+      U << -M;
+      Matrix X1 = M.Rows(2,4);
+      Matrix Y1 = U.t().Rows(2,4);
+      Matrix X = U; { Print(Matrix(X.Columns(2,4).t()-Y1)); }
+      RowVector RV = M.Row(5);
+      {
+         X.ReSize(3,10);
+         X.Row(1) << M.Row(2); X.Row(2) << M.Row(3); X.Row(3) << M.Row(4);
+         Print(Matrix(X-X1));
+      }
+      {
+         UpperTriangularMatrix V = U.SymSubMatrix(3,5);
+         Matrix MV = U.SubMatrix(3,5,3,5); { Print(Matrix(MV-V)); }
+         Matrix X2 = M.t().Columns(2,4); { Print(Matrix(X2-X1.t())); }
+         Matrix Y2 = U.Columns(2,4); { Print(Matrix(Y2-Y1.t())); }
+         ColumnVector CV = M.t().Column(5); { Print(ColumnVector(CV-RV.t())); }
+         X.ReSize(10,3); M = M.t();
+         X.Column(1) << M.Column(2); X.Column(2) << M.Column(3);
+         X.Column(3) << M.Column(4);
+         Print(Matrix(X-X2));
+      }
+   }
+
+   {
+      Tracer et1("Stage 2");
+      int i, j;
+      Matrix M; Matrix X; M.ReSize(5,8);
+      for (i=1;i<=5;i++) for (j=1;j<=8;j++) M(i,j) = 100*i+j;
+      {
+         X = M.Columns(5,8); M.Columns(5,8) << M.Columns(1,4);
+             M.Columns(1,4) << X;
+         X = M.Columns(3,4); M.Columns(3,4) << M.Columns(1,2);
+             M.Columns(1,2) << X;
+         X = M.Columns(7,8); M.Columns(7,8) << M.Columns(5,6);
+             M.Columns(5,6) << X;
+      }
+      {
+         X = M.Column(2); M.Column(2) = M.Column(1); M.Column(1) = X;
+         X = M.Column(4); M.Column(4) = M.Column(3); M.Column(3) = X;
+         X = M.Column(6); M.Column(6) = M.Column(5); M.Column(5) = X;
+         X = M.Column(8); M.Column(8) = M.Column(7); M.Column(7) = X;
+         X.ReSize(5,8);
+      }
+      for (i=1;i<=5;i++) for (j=1;j<=8;j++) X(i,9-j) = 100*i+j;
+      Print(Matrix(X-M));
+   }
+   {
+      Tracer et1("Stage 3");
+      // try submatrices of zero dimension
+      int i, j;
+      Matrix A(4,5); Matrix B, C;
+      for (i=1; i<=4; i++) for (j=1; j<=5; j++)
+         A(i,j) = 100+i*10+j;
+      B = A + 100;
+      C = A | B.Columns(4,3); Print(Matrix(A - C));
+      C = A | B.Columns(1,0); Print(Matrix(A - C));
+      C = A | B.Columns(6,5); Print(Matrix(A - C));
+      C = A & B.Rows(2,1); Print(Matrix(A - C));
+   }
+   {
+      Tracer et1("Stage 4");
+      BandMatrix BM(5,3,2);
+      BM(1,1) = 1; BM(1,2) = 2; BM(1,3) = 3;
+      BM(2,1) = 4; BM(2,2) = 5; BM(2,3) = 6; BM(2,4) = 7;
+      BM(3,1) = 8; BM(3,2) = 9; BM(3,3) =10; BM(3,4) =11; BM(3,5) =12;
+      BM(4,1) =13; BM(4,2) =14; BM(4,3) =15; BM(4,4) =16; BM(4,5) =17;
+                   BM(5,2) =18; BM(5,3) =19; BM(5,4) =20; BM(5,5) =21;
+      SymmetricBandMatrix SM(5,3);
+      SM.Inject(BandMatrix(BM + BM.t()));
+      Matrix A = BM + 1;
+      Matrix M = A + A.t() - 2;
+      Matrix C = A.i() * BM;
+      C = A * C - BM; Clean(C, 0.000000001); Print(C);
+      C = A.i() * SM;
+      C = A * C - M; Clean(C, 0.000000001); Print(C);
+
+      // check row-wise load
+      BandMatrix BM1(5,3,2);
+      BM1.Row(1) <<  1 <<  2 <<  3;
+      BM1.Row(2) <<  4 <<  5 <<  6 <<  7;
+      BM1.Row(3) <<  8 <<  9 << 10 << 11 << 12;
+      BM1.Row(4) << 13 << 14 << 15 << 16 << 17;
+      BM1.Row(5)       << 18 << 19 << 20 << 21;
+      Matrix M1 = BM1 - BM; Print(M1);
+   }
+   {
+      Tracer et1("Stage 5");
+      Matrix X(4,4);
+      X << 1 << 2 << 3 << 4
+        << 5 << 6 << 7 << 8
+        << 9 <<10 <<11 <<12
+        <<13 <<14 <<15 <<16;
+      Matrix Y(4,0);
+      Y = X | Y;
+      X -= Y; Print(X);
+
+      DiagonalMatrix D(1);
+      D << 23;                       // matrix input with just one value
+      D(1) -= 23; Print(D);
+
+   }
+   {
+      Tracer et1("Stage 6");
+      Matrix h (2,2);
+      h << 1.0 << 2.0 << 0.0 << 1.0 ;
+      RowVector c(2);
+      c << 0.0 << 1.0;
+      h -= c & c;
+      h -= c.t().Reverse() | c.Reverse().t();
+      Print(h);
+   }
+   {
+      Tracer et1("Stage 7");
+      // Check row-wise input for diagonal matrix
+      DiagonalMatrix D(4);
+      D << 18 << 23 << 31 << 17;
+      DiagonalMatrix D1(4);
+      D1.Row(1) << 18; D1.Row(2) << 23; D1.Row(3) << 31; D1.Row(4) << 17;
+      D1 -= D; Print(D1);
+      D1(1) = 18; D1(2) = 23; D1(3) = 31; D1(4) = 17;
+      D1 -= D; Print(D1);
+   }
+   
+   {
+      Tracer et1("Stage 8");
+      // test swap functions
+      MultWithCarry MWC;
+      Matrix A(3,4); Matrix B(5,6);
+      FillWithValues(MWC, A); FillWithValues(MWC, B);
+      Matrix A1 = A; Matrix B1 = B; A.Release(); B.Release(2);
+      swap(A, B);
+      int a = A.size() - B1.size(), b = B.size() - A1.size();
+      Matrix D = A - B1; Print(D);
+      D = B - A1; Print(D);
+      Print(B);   // should be zero because of release
+      D = A - B1; Print(D);
+      Print(A);   // now should be zero
+      D.ReSize(1,2); D(1,1) = a; D(1,2) = b; Print(D);
+      
+      A.ReSize(20,20); FillWithValues(MWC, A);
+     
+      UpperTriangularMatrix UA; UA << A; UpperTriangularMatrix UA1 = UA;
+      UpperTriangularMatrix UB;
+      swap(UA, UB); Print(UA); UB -= UA1; Print(UB);
+      
+      LowerTriangularMatrix LA; LA << A; LowerTriangularMatrix LA1 = LA;
+      LowerTriangularMatrix LB;
+      swap(LB, LA); Print(LA); LB -= LA1; Print(LB);
+
+      SymmetricMatrix SA; SA << A; SymmetricMatrix SA1 = SA;
+      SymmetricMatrix SB;
+      swap(SA, SB); Print(SA); SB -= SA1; Print(SB);
+      
+      DiagonalMatrix DA; DA << A; DiagonalMatrix DA1 = DA;
+      DiagonalMatrix DB;
+      swap(DB, DA); Print(DA); DB -= DA1; Print(DB);
+      
+      RowVector RVA = A.Row(1); RowVector RVA1 = RVA;
+      RowVector RVB;
+      swap(RVB, RVA); Print(RVA); RVB -= RVA1; Print(RVB);
+      
+      ColumnVector CVA = A.Column(1); ColumnVector CVA1 = CVA;
+      ColumnVector CVB;
+      swap(CVA, CVB); Print(CVA); CVB -= CVA1; Print(CVB);
+      
+      BandMatrix BA(20, 7, 4); BA.Inject(A); BandMatrix BA1 = BA;
+      BandMatrix BB;
+      swap(BA, BB); D = BA; Print(D); BB -= BA1; D = BB; Print(D);
+      
+      LowerBandMatrix LBA(20, 6); LBA.Inject(A); LowerBandMatrix LBA1 = LBA;
+      BandMatrix LBB;
+      swap(LBB, LBA); D = LBA; Print(D); LBB -= LBA1; D = LBB; Print(D);
+      
+      UpperBandMatrix UBA(20, 9); UBA.Inject(A); UpperBandMatrix UBA1 = UBA;
+      UpperBandMatrix UBB;
+      swap(UBA, UBB); D = UBA; Print(D); UBB -= UBA1; D = UBB; Print(D);
+      
+      SymmetricBandMatrix SBA(20, 4); SBA.Inject(A);
+      SymmetricBandMatrix SBA1 = SBA;
+      SymmetricBandMatrix SBB;
+      
+      swap(SBB, SBA); D = SBA; Print(D);
+      SBB -= SBA1; D = SBB; Print(D);
+      
+      B.ReSize(10,10); FillWithValues(MWC, B);
+      
+      CroutMatrix CA = A; IdentityMatrix IA(20);
+      CroutMatrix CB = B; IdentityMatrix IB(10);
+      swap(CA, CB); swap(IA, IB);
+      D = CA.i() * B - IA; Clean(D,0.00000001); Print(D);
+      D = CB.i() * A - IB; Clean(D,0.00000001); Print(D);
+      
+      BA.ReSize(20, 5, 7); BA.Inject(A); BandLUMatrix BLUA = BA;
+      BB.ReSize(10, 3, 4); BB.Inject(B); BandLUMatrix BLUB = BB;
+      swap(BLUA, BLUB);
+      D = BLUA.i() * BB - IA; Clean(D,0.00000001); Print(D);
+      D = BLUB.i() * BA - IB; Clean(D,0.00000001); Print(D);
+
+      
+      SBA.ReSize(20, 5); SBA.Inject(A); BandLUMatrix SBLUA = SBA;
+      SBB.ReSize(10, 3); SBB.Inject(B); BandLUMatrix SBLUB = SBB;
+      swap(SBLUA, SBLUB);
+      D = SBLUA.i() * SBB - IA; Clean(D,0.00000001); Print(D);
+      D = SBLUB.i() * SBA - IB; Clean(D,0.00000001); Print(D);
+      
+      UA << A;
+      GenericMatrix GUA = UA; GenericMatrix GB = B; swap(GUA, GB);
+      D = GB - UA; Print(D); D = B - GUA; Print(D);
+      
+   }
+
+//   cout << "\nEnd of fourth test\n";
+}
+
Index: Shared/newmat/extra/tmt5.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt5.cpp
diff -N Shared/newmat/extra/tmt5.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt5.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,125 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+// **************************** test program ******************************
+
+
+
+ReturnMatrix Returner0(const GenericMatrix& GM)
+{ Matrix M = GM; M.Release(); return M; }
+
+ReturnMatrix Returner1(const GenericMatrix& GM)
+{ Matrix M = GM+1; M.Release(); return M; }
+
+ReturnMatrix Returner2(const GenericMatrix& GM)
+{ UpperBandMatrix M = GM*2; M.Release(); return M; }
+
+ReturnMatrix Returner3(const GenericMatrix& GM)
+{ LowerBandMatrix M = GM*3; M.Release(); return M; }
+
+ReturnMatrix Returner4(const GenericMatrix& GM)
+{ SymmetricMatrix M = GM+4; M.Release(); return M; }
+
+ReturnMatrix Returner5(const GenericMatrix& GM)
+{ SymmetricBandMatrix M = GM*5; M.Release(); return M; }
+
+ReturnMatrix Returner6(const GenericMatrix& GM)
+{ BandMatrix M = GM*6; M.Release(); return M; }
+
+ReturnMatrix Returner7(const GenericMatrix& GM)
+{ DiagonalMatrix M = GM*7; M.Release(); return M; }
+
+void trymat5()
+{
+//   cout << "\nFifth test of Matrix package\n";
+   Tracer et("Fifth test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i,j;
+
+   Matrix A(5,6);
+   for (i=1;i<=5;i++) for (j=1;j<=6;j++) A(i,j)=1+i*j+i*i+j*j;
+   ColumnVector CV(6);
+   for (i=1;i<=6;i++) CV(i)=i*i+3;
+   ColumnVector CV2(5); for (i=1;i<=5;i++) CV2(i)=1.0;
+   ColumnVector CV1=CV;
+
+   {
+      CV=A*CV;
+      RowVector RV=CV.t(); // RowVector RV; RV=CV.t();
+      RV=RV-1.0;
+      CV=(RV*A).t()+A.t()*CV2; CV1=(A.t()*A)*CV1 - CV;
+      Print(CV1);
+   }
+
+   CV1.ReSize(6);
+   CV2.ReSize(6);
+   CV.ReSize(6);
+   for (i=1;i<=6;i++) { CV1(i)=i*3+1; CV2(i)=10-i; CV(i)=11+i*2; }
+   ColumnVector CX=CV2-CV; { CX=CX+CV1; Print(CX); }
+   Print(ColumnVector(CV1+CV2-CV));
+   RowVector RV=CV.t(); RowVector RV1=CV1.t();
+   RowVector R=RV-RV1; Print(RowVector(R-CV2.t()));
+
+// test loading of list
+
+   RV.ReSize(10);
+   for (i=1;i<=10;i++) RV(i) = i*i;
+   RV1.ReSize(10);
+   RV1 << 1 << 4 << 9 << 16 << 25 << 36 << 49 << 64 << 81 << 100; // << 121;
+   Print(RowVector(RV-RV1));
+
+   et.ReName("Fifth test of Matrix package - almost at end");
+
+   Matrix X(2,3);
+   X << 11 << 12 << 13
+     << 21 << 22 << 23;
+
+   Matrix Y = X.t();                 // check simple transpose
+
+   X(1,1) -= 11; X(1,2) -= 12; X(1,3) -= 13;
+   X(2,1) -= 21; X(2,2) -= 22; X(2,3) -= 23;
+   Print(X);
+
+   Y(1,1) -= 11; Y(2,1) -= 12; Y(3,1) -= 13;
+   Y(1,2) -= 21; Y(2,2) -= 22; Y(3,2) -= 23;
+   Print(Y);
+
+   et.ReName("Fifth test of Matrix package - at end");
+
+   RV = Returner1(RV)-1; Print(RowVector(RV-RV1));
+   CV1 = Returner1(RV.t())-1; Print(ColumnVector(RV.t()-CV1));
+#ifndef DONT_DO_NRIC
+   nricMatrix AA = A;
+   X = Returner1(AA)-A-1; Print(X);
+#endif
+   UpperTriangularMatrix UT(31);
+   for (i=1; i<=31; i++) for (j=i; j<=31; j++) UT(i,j) = i+j+(i-j)*(i-2*j);
+   UpperBandMatrix UB(31,5); UB.Inject(UT);
+   LowerTriangularMatrix LT = UT.t();
+   LowerBandMatrix LB(31,5); LB.Inject(LT);
+   A = Returner0(UB)-LB.t(); Print(A);
+   A = Returner2(UB).t()-LB*2; Print(A);
+   A = Returner3(LB).t()-UB*3; Print(A);
+   SymmetricMatrix SM; SM << (UT+LT);
+   A = Returner4(SM)-UT-LT-4; Print(A);
+   SymmetricBandMatrix SB(31,5); SB.Inject(SM);
+   A = Returner5(SB)/5-UB-LB; Print(A);
+   BandMatrix B = UB+LB*LB; A = LB;
+   A = Returner6(B)/6 - UB - A*A; Print(A);
+   DiagonalMatrix D; D << UT;
+   D << (Returner7(D)/7 - UT); Print(D);
+
+//   cout << "\nEnd of fifth test\n";
+}
Index: Shared/newmat/extra/tmt6.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt6.cpp
diff -N Shared/newmat/extra/tmt6.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt6.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,155 @@
+
+//#define WANT_STREAM
+#define WANT_MATH
+
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+// slow sort program
+
+static void SimpleSortDescending(Real* first, const int length)
+{
+   int i = length;
+   while (--i)
+   {
+      Real x = *first; Real* f = first; Real* g = f;
+      int j = i;
+      while (j--) if (x < *(++f)) { g = f; x = *g; }
+      *g = *first; *first++ = x;
+   }
+}
+
+static void TestSort(int n)
+{
+   // make some data
+   RowVector X(n);
+   int i;
+   for (i = 1; i <= n; i++)
+      X(i) = sin((Real)i) + 0.3 * cos(i/5.0) - 0.6 * sin(i/7.0) + 0.2 * sin(2.0 * i);
+   RowVector X_Sorted = X; SimpleSortDescending(X_Sorted.Store(), n);
+   RowVector A = X + X.Reverse(); SimpleSortDescending(A.Store(), n);
+
+   // test descending sort
+
+   RowVector Y = X; SortDescending(Y); Y -= X_Sorted; Print(Y);
+   Y = X_Sorted; SortDescending(Y); Y -= X_Sorted; Print(Y);
+   Y = X_Sorted.Reverse(); SortDescending(Y); Y -= X_Sorted; Print(Y);
+   Y = X + X.Reverse(); SortDescending(Y); Y -= A; Print(Y);
+
+   // test ascending sort
+
+   Y = X; SortAscending(Y); Y -= X_Sorted.Reverse(); Print(Y);
+   Y = X_Sorted; SortAscending(Y); Y -= X_Sorted.Reverse(); Print(Y);
+   Y = X_Sorted.Reverse(); SortAscending(Y); Y -= X_Sorted.Reverse(); Print(Y);
+   Y = X + X.Reverse(); SortAscending(Y); Y -= A.Reverse(); Print(Y);
+}
+
+
+void trymat6()
+{
+   Tracer et("Sixth test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i,j;
+
+
+   DiagonalMatrix D(6);
+   UpperTriangularMatrix U(6);
+   for (i=1;i<=6;i++) { for (j=i;j<=6;j++) U(i,j)=i*i*i-50; D(i,i)=i*i+i-10; }
+   LowerTriangularMatrix L=(U*3.0).t();
+   SymmetricMatrix S(6);
+   for (i=1;i<=6;i++) for (j=i;j<=6;j++) S(i,j)=i*i+2.0+j;
+   Matrix MD=D; Matrix ML=L; Matrix MU=U; Matrix MS=S;
+   Matrix M(6,6);
+   for (i=1;i<=6;i++) for (j=1;j<=6;j++) M(i,j)=i*j+i*i-10.0;  
+   {
+      Tracer et1("Stage 1");
+      Print(Matrix(MS+(-MS)));
+      Print(Matrix((S+M)-(MS+M)));
+      Print(Matrix((M+U)-(M+MU)));
+      Print(Matrix((M+L)-(M+ML)));
+   }
+   {
+      Tracer et1("Stage 2");
+      Print(Matrix((M+D)-(M+MD)));
+      Print(Matrix((U+D)-(MU+MD)));
+      Print(Matrix((D+L)-(ML+MD)));
+      Print(Matrix((-U+D)+MU-MD));
+      Print(Matrix((-L+D)+ML-MD));
+   }
+   {
+      Tracer et1("Stage 3 - concatenate");
+      RowVector A(5);
+      A << 1 << 2 << 3 << 4 << 5;
+      RowVector B(5);
+      B << 3 << 1 << 4 << 1 << 5;
+      Matrix C(3,5);
+      C <<  2 <<  3 <<  5 <<  7 << 11
+        << 13 << 17 << 19 << 23 << 29
+        << 31 << 37 << 41 << 43 << 47;
+      Matrix X1 = A & B & C;
+      Matrix X2 = (A.t() | B.t() | C.t()).t();
+      Matrix X3(5,5);
+      X3.Row(1)=A; X3.Row(2)=B; X3.Rows(3,5)=C;
+      Print(Matrix(X1-X2));
+      Print(Matrix(X1-X3));
+      LowerTriangularMatrix LT1; LT1 << (A & B & C);
+      UpperTriangularMatrix UT1; UT1 << (A.t() | B.t() | C.t());
+      Print(LowerTriangularMatrix(LT1-UT1.t()));
+      DiagonalMatrix D1; D1 << (A.t() | B.t() | C.t());
+      ColumnVector At = A.t();
+      ColumnVector Bt = B.t();
+      Matrix Ct = C.t();
+      LowerTriangularMatrix LT2; LT2 << (At | Bt | Ct);
+      UpperTriangularMatrix UT2; UT2 << (At.t() & Bt.t() & Ct.t());
+      Matrix ABt = At | Bt;
+      DiagonalMatrix D2; D2 << (ABt | Ct);
+      Print(LowerTriangularMatrix(LT2-UT2.t()));
+      Print(DiagonalMatrix(D1-D2));
+      Print(Matrix(LT1+UT2-D2-X1));
+      Matrix M1 = LT1 | UT2; Matrix M2 = UT1 & LT2;
+      Print(Matrix(M1-M2.t()));
+      M1 = UT2 | LT1; M2 = LT2 & UT1;
+      Print(Matrix(M1-M2.t()));
+      M1 = (LT1 | UT2) & (UT2 | LT1);
+      M2 = (UT1 & LT2) | (LT2 & UT1);
+      Print(Matrix(M1-M2.t()));
+      SymmetricMatrix SM1; SM1 << (M1 + M1.t());
+      SymmetricMatrix SM2; SM2 << ((SM1 | M1) & (M1.t() | SM1));
+      Matrix M3(20,20);
+      M3.SubMatrix(1,10,1,10) = SM1;
+      M3.SubMatrix(1,10,11,20) = M1;
+      M3.SubMatrix(11,20,1,10) = M2;
+      M3.SubMatrix(11,20,11,20) = SM1;
+      Print(Matrix(M3-SM2));
+
+      SymmetricMatrix SM(15); SM = 0; SM.SymSubMatrix(1,10) = SM1;
+      M3.ReSize(15,15); M3 = 0; M3.SubMatrix(1,10,1,10) = SM1;
+      M3 -= SM; Print(M3);
+      SM = 0; SM.SymSubMatrix(6,15) = SM1;
+      M3.ReSize(15,15); M3 = 0; M3.SubMatrix(6,15,6,15) = SM1;
+      M3 = M3.t() - SM; Print(M3);
+   }
+   {
+      Tracer et1("Stage 4 - sort");
+      TestSort(1); TestSort(2); TestSort(3); TestSort(4);
+      TestSort(15); TestSort(16); TestSort(17); TestSort(18);
+      TestSort(99); TestSort(100); TestSort(101);
+   }
+
+
+//   cout << "\nEnd of sixth test\n";
+}
+
Index: Shared/newmat/extra/tmt7.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt7.cpp
diff -N Shared/newmat/extra/tmt7.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt7.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,162 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+// C matrix mulitply - for testing RealStarStar
+
+void c_matrix_multiply(int p, int q, int r,
+   const Real** a, const Real** b, Real** c)
+{
+   for (int i = 0; i < p; ++i) for (int k = 0; k < r; ++k)
+   {
+      Real sum = 0.0;
+      for (int j = 0; j < q; ++j) sum += a[i][j] * b[j][k];
+      c[i][k] = sum;
+   }
+}
+   
+
+
+void trymat7()
+{
+//   cout << "\nSeventh test of Matrix package\n";
+   Tracer et("Seventh test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i,j;
+
+
+   DiagonalMatrix D(6);
+   UpperTriangularMatrix U(6);
+   for (i=1;i<=6;i++) { for (j=i;j<=6;j++) U(i,j)=i*i*j-50; D(i,i)=i*i+i-10; }
+   LowerTriangularMatrix L=(U*3.0).t();
+   SymmetricMatrix S(6);
+   for (i=1;i<=6;i++) for (j=i;j<=6;j++) S(i,j)=i*i+2.0+j;
+   Matrix MD=D; Matrix ML=L; Matrix MU=U;
+   Matrix MS=S;
+   Matrix M(6,6);
+   for (i=1;i<=6;i++) for (j=1;j<=6;j++) M(i,j)=i*j+i*i-10.0;  
+   {
+      Tracer et1("Stage 1");
+      Print(Matrix((S-M)-(MS-M)));
+      Print(Matrix((-M-S)+(MS+M)));
+      Print(Matrix((U-M)-(MU-M)));
+   }
+   {
+      Tracer et1("Stage 2");
+      Print(Matrix((L-M)+(M-ML)));
+      Print(Matrix((D-M)+(M-MD)));
+      Print(Matrix((D-S)+(MS-MD)));
+      Print(Matrix((D-L)+(ML-MD)));
+   }
+
+   { M=MU.t(); }
+   LowerTriangularMatrix LY=D.i()*U.t();
+   {
+      Tracer et1("Stage 3");
+      MS=D*LY-M; Clean(MS,0.00000001); Print(MS);
+      L=U.t();
+      LY=D.i()*L; MS=D*LY-M; Clean(MS,0.00000001); Print(MS);
+   }
+   {
+      Tracer et1("Stage 4");
+      UpperTriangularMatrix UT(11);
+      int i, j;
+      for (i=1;i<=11;i++) for (j=i;j<=11;j++) UT(i,j)=i*i+j*3;
+      GenericMatrix GM; Matrix X;
+      UpperBandMatrix UB(11,3); UB.Inject(UT); UT = UB;
+      UpperBandMatrix UB2 = UB / 8;
+      GM = UB2-UT/8; X = GM; Print(X);
+      SymmetricBandMatrix SB(11,4); SB << (UB + UB.t());
+      X = SB - UT - UT.t(); Print(X);
+      BandMatrix B = UB + UB.t()*2;
+      DiagonalMatrix D; D << B;
+      X.ReSize(1,1); X(1,1) = Trace(B)-Sum(D); Print(X);
+      X = SB + 5; Matrix X1=X; X = SP(UB,X); Matrix X2 =UB;
+      X1 = (X1.AsDiagonal() * X2.AsDiagonal()).AsRow()-X.AsColumn().t();
+      Print(X1);
+      X1=SB.t(); X2 = B.t(); X = SB.i() * B - X1.i() * X2.t();
+      Clean(X,0.00000001); Print(X);
+      X = SB.i(); X = X * B - X1.i() * X2.t();
+      Clean(X,0.00000001); Print(X);
+      D = 1; X = SB.i() * SB - D; Clean(X,0.00000001); Print(X);
+      ColumnVector CV(11);
+      CV << 2 << 6 <<3 << 8 << -4 << 17.5 << 2 << 1 << -2 << 5 << 3.75;
+      D << 2 << 6 <<3 << 8 << -4 << 17.5 << 2 << 1 << -2 << 5 << 3.75;
+      X = CV.AsDiagonal(); X = X-D; Print(X);
+      SymmetricBandMatrix SB1(11,7); SB1 = 5; 
+      SymmetricBandMatrix SB2 = SB1 + D;
+      X.ReSize(11,11); X=0;
+      for (i=1;i<=11;i++) for (j=1;j<=11;j++)
+      {
+         if (abs(i-j)<=7) X(i,j)=5;
+         if (i==j) X(i,j)+=CV(i);
+      }
+      SymmetricMatrix SM; SM.ReSize(11);
+      SM=SB; SB = SB+SB2; X1 = SM+X-SB; Print(X1);
+      SB2=0; X2=SB2; X1=SB; Print(X2);
+      for (i=1;i<=11;i++) SB2.Column(i)<<SB.Column(i);
+      X1=X1-SB2; Print(X1);
+      X = SB; SB2.ReSize(11,4); SB2 = SB*5; SB2 = SB + SB2;
+      X1 = X*6 - SB2; Print(X1);
+      X1 = SP(SB,SB2/3); X1=X1-SP(X,X*2); Print(X1);
+      X1 = SP(SB2/6,X*2); X1=X1-SP(X*2,X); Print(X1);
+   }
+
+   {
+      // test the simple integer array class
+      Tracer et("Stage 5");
+      ColumnVector Test(10); Test = 0.0;
+      int i;
+      SimpleIntArray A(100);
+      for (i = 0; i < 100; i++) A[i] = i*i+1;
+      SimpleIntArray B(100), C(50), D;
+      B = A; A.ReSize(50, true); C = A; A.ReSize(150, true); D = A;
+      for (i = 0; i < 100; i++) if (B[i] != i*i+1) Test(1)=1;
+      for (i = 0; i < 50; i++) if (C[i] != i*i+1) Test(2)=1;
+      for (i = 0; i < 50; i++) if (D[i] != i*i+1) Test(3)=1;
+      A.resize(75); A = A.size();
+      for (i = 0; i < 75; i++) if (A[i] != 75) Test(4)=1;
+      A.resize(25); A = A.size();
+      for (i = 0; i < 25; i++) if (A[i] != 25) Test(5)=1;
+      A.ReSize(25); A = 23;
+      for (i = 0; i < 25; i++) if (A[i] != 23) Test(6)=1;
+      A.ReSize(0); A.ReSize(15); A = A.Size();
+      for (i = 0; i < 15; i++) if (A[i] != 15) Test(7)=1;
+      const SimpleIntArray E = B;
+      for (i = 0; i < 100; i++) if (E[i] != i*i+1) Test(8)=1;
+      Print(Test);
+   }
+   
+   {
+      // testing RealStarStar
+      Tracer et("Stage 6");
+      MultWithCarry MWC;
+      
+      Matrix A(10, 12), B(12, 15), C(10, 15);
+      FillWithValues(MWC, A); FillWithValues(MWC, B);
+      ConstRealStarStar a(A);
+      ConstRealStarStar b(B);
+      RealStarStar c(C);
+      c_matrix_multiply(10,12,15,a,b,c);
+      Matrix X = C - A * B; Clean(X,0.00000001); Print(X);
+      A.ReSize(11, 10); B.ReSize(10,8); C.ReSize(11,8);
+      FillWithValues(MWC, A); FillWithValues(MWC, B);
+      C = -1;
+      c_matrix_multiply(11,10,8,
+         ConstRealStarStar(A),ConstRealStarStar(B),RealStarStar(C));
+      X = C - A * B; Clean(X,0.00000001); Print(X);
+   }    
+
+
+//   cout << "\nEnd of seventh test\n";
+}
Index: Shared/newmat/extra/tmt8.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt8.cpp
diff -N Shared/newmat/extra/tmt8.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt8.cpp	16 Jun 2004 21:16:45 -0000	1.1
@@ -0,0 +1,288 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+// **************************** test program ******************************
+
+
+void Transposer(const GenericMatrix& GM1, GenericMatrix&GM2)
+   { GM2 = GM1.t(); }
+
+// this is a routine in "Numerical Recipes in C" format
+// if R is a row vector, C a column vector and D diagonal
+// make matrix DCR
+
+static void DCR(Real d[], Real c[], int m, Real r[], int n, Real **dcr)
+{
+   int i, j;
+   for (i = 1; i <= m; i++) for (j = 1; j <= n; j++)
+   dcr[i][j] = d[i] * c[i] * r[j];
+}
+
+ReturnMatrix TestReturn(const GeneralMatrix& gm) { return gm; }
+
+void trymat8()
+{
+//   cout << "\nEighth test of Matrix package\n";
+   Tracer et("Eighth test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i;
+
+
+   DiagonalMatrix D(6);
+   for (i=1;i<=6;i++)  D(i,i)=i*i+i-10;
+   DiagonalMatrix D2=D;
+   Matrix MD=D;
+
+   DiagonalMatrix D1(6); for (i=1;i<=6;i++) D1(i,i)=-100+i*i*i;
+   Matrix MD1=D1;
+   Print(Matrix(D*D1-MD*MD1));
+   Print(Matrix((-D)*D1+MD*MD1));
+   Print(Matrix(D*(-D1)+MD*MD1));
+   DiagonalMatrix DX=D;
+   {
+      Tracer et1("Stage 1");
+      DX=(DX+D1)*DX; Print(Matrix(DX-(MD+MD1)*MD));
+      DX=D;
+      DX=-DX*DX+(DX-(-D1))*((-D1)+DX);
+      // Matrix MX = Matrix(MD1);
+      // MD1=DX+(MX.t())*(MX.t()); Print(MD1);
+      MD1=DX+(Matrix(MD1).t())*(Matrix(MD1).t()); Print(MD1);
+      DX=D; DX=DX; DX=D2-DX; Print(DiagonalMatrix(DX));
+      DX=D;
+   }
+   {
+      Tracer et1("Stage 2");
+      D.Release(2);
+      D1=D; D2=D;
+      Print(DiagonalMatrix(D1-DX));
+      Print(DiagonalMatrix(D2-DX));
+      MD1=1.0;
+      Print(Matrix(MD1-1.0));
+   }
+   {
+      Tracer et1("Stage 3");
+      //GenericMatrix
+      LowerTriangularMatrix LT(4);
+      LT << 1 << 2 << 3 << 4 << 5 << 6  << 7 << 8 << 9 << 10;
+      UpperTriangularMatrix UT = LT.t() * 2.0;
+      GenericMatrix GM1 = LT;
+      LowerTriangularMatrix LT1 = GM1-LT; Print(LT1);
+      GenericMatrix GM2 = GM1; LT1 = GM2; LT1 = LT1-LT; Print(LT1);
+      GM2 = GM1; LT1 = GM2; LT1 = LT1-LT; Print(LT1);
+      GM2 = GM1*2; LT1 = GM2; LT1 = LT1-LT*2; Print(LT1);
+      GM1.Release();
+      GM1=GM1; LT1=GM1-LT; Print(LT1); LT1=GM1-LT; Print(LT1);
+      GM1.Release();
+      GM1=GM1*4; LT1=GM1-LT*4; Print(LT1);
+      LT1=GM1-LT*4; Print(LT1); GM1.CleanUp();
+      GM1=LT; GM2=UT; GM1=GM1*GM2; Matrix M=GM1; M=M-LT*UT; Print(M);
+      Transposer(LT,GM2); LT1 = LT - GM2.t(); Print(LT1);
+      GM1=LT; Transposer(GM1,GM2); LT1 = LT - GM2.t(); Print(LT1);
+      GM1 = LT; GM1 = GM1 + GM1; LT1 = LT*2-GM1; Print(LT1);
+      DiagonalMatrix D; D << LT; GM1 = D; LT1 = GM1; LT1 -= D; Print(LT1);
+      UpperTriangularMatrix UT1 = GM1; UT1 -= D; Print(UT1);
+   }
+   {
+      Tracer et1("Stage 4");
+      // Another test of SVD
+      Matrix M(12,12); M = 0;
+      M(1,1) = M(2,2) = M(4,4) = M(6,6) =
+         M(7,7) = M(8,8) = M(10,10) = M(12,12) = -1;
+      M(1,6) = M(1,12) = -5.601594;
+      M(3,6) = M(3,12) = -0.000165;
+      M(7,6) = M(7,12) = -0.008294;
+      DiagonalMatrix D;
+      SVD(M,D);
+      SortDescending(D);
+      // answer given by matlab
+      DiagonalMatrix DX(12);
+      DX(1) = 8.0461;
+      DX(2) = DX(3) = DX(4) = DX(5) = DX(6) = DX(7) = 1;
+      DX(8) = 0.1243;
+      DX(9) = DX(10) = DX(11) = DX(12) = 0;
+      D -= DX; Clean(D,0.0001); Print(D);
+   }
+#ifndef DONT_DO_NRIC
+   {
+      Tracer et1("Stage 5");
+      // test numerical recipes in C interface
+      DiagonalMatrix D(10);
+      D << 1 << 4 << 6 << 2 << 1 << 6 << 4 << 7 << 3 << 1;
+      ColumnVector C(10);
+      C << 3 << 7 << 5 << 1 << 4 << 2 << 3 << 9 << 1 << 3;
+      RowVector R(6);
+      R << 2 << 3 << 5 << 7 << 11 << 13;
+      nricMatrix M(10, 6);
+      DCR( D.nric(), C.nric(), 10, R.nric(), 6, M.nric() );
+      M -= D * C * R;  Print(M);
+
+      D.ReSize(5);
+      D << 1.25 << 4.75 << 9.5 << 1.25 << 3.75;
+      C.ReSize(5);
+      C << 1.5 << 7.5 << 4.25 << 0.0 << 7.25;
+      R.ReSize(9);
+      R << 2.5 << 3.25 << 5.5 << 7 << 11.25 << 13.5 << 0.0 << 1.5 << 3.5;
+      Matrix MX = D * C * R;
+      M.ReSize(MX);
+      DCR( D.nric(), C.nric(), 5, R.nric(), 9, M.nric() );
+      M -= MX;  Print(M);
+      
+      // test swap
+      nricMatrix A(3,4); nricMatrix B(4,5);
+      A.Row(1) << 2 << 7 << 3 << 6;
+      A.Row(2) << 6 << 2 << 5 << 9;
+      A.Row(3) << 1 << 0 << 1 << 6;
+      B.Row(1) << 2 << 8 << 4 << 5 << 3;
+      B.Row(2) << 1 << 7 << 5 << 3 << 9;
+      B.Row(3) << 7 << 8 << 2 << 1 << 6;
+      B.Row(4) << 5 << 2 << 9 << 0 << 9;
+      nricMatrix A1(1,2); nricMatrix B1;
+      nricMatrix X(3,5); Matrix X1 = A * B;
+      swap(A, A1); swap(B1, B);
+      for (int i = 1; i <= 3; ++i) for (int j = 1; j <= 5; ++j)
+      {
+         X.nric()[i][j] = 0.0;
+         for (int k = 1; k <= 4; ++k)
+            X.nric()[i][j] += A1.nric()[i][k] * B1.nric()[k][j];
+      }
+      X1 -= X; Print(X1); 
+   }
+#endif
+   {
+      Tracer et1("Stage 6");
+      // test dotproduct
+      DiagonalMatrix test(5); test = 1;
+      ColumnVector C(10);
+      C << 3 << 7 << 5 << 1 << 4 << 2 << 3 << 9 << 1 << 3;
+      RowVector R(10);
+      R << 2 << 3 << 5 << 7 << 11 << 13 << -3 << -4 << 2 << 4;
+      test(1) = (R * C).AsScalar() - DotProduct(C, R);
+      test(2) = C.SumSquare() - DotProduct(C, C);
+      test(3) = 6.0 * (C.t() * R.t()).AsScalar() - DotProduct(2.0 * C, 3.0 * R);
+      Matrix MC = C.AsMatrix(2,5), MR = R.AsMatrix(5,2);
+      test(4) = DotProduct(MC, MR) - (R * C).AsScalar();
+      UpperTriangularMatrix UT(5);
+      UT << 3 << 5 << 2 << 1 << 7
+              << 1 << 1 << 8 << 2
+                   << 7 << 0 << 1
+                        << 3 << 5
+                             << 6;
+      LowerTriangularMatrix LT(5);
+      LT << 5
+         << 2 << 3
+         << 1 << 0 << 7
+         << 9 << 8 << 1 << 2
+         << 0 << 2 << 1 << 9 << 2;
+      test(5) = DotProduct(UT, LT) - Sum(SP(UT, LT));
+      Print(test);
+      // check row-wise load;
+      LowerTriangularMatrix LT1(5);
+      LT1.Row(1) << 5;
+      LT1.Row(2) << 2   << 3;
+      LT1.Row(3) << 1   << 0   << 7;
+      LT1.Row(4) << 9   << 8   << 1   << 2;
+      LT1.Row(5) << 0   << 2   << 1   << 9   << 2;
+      Matrix M = LT1 - LT; Print(M);
+      // check solution with identity matrix
+      IdentityMatrix IM(5); IM *= 2;
+      LinearEquationSolver LES1(IM);
+      LowerTriangularMatrix LTX = LES1.i() * LT;
+      M = LTX * 2 - LT; Print(M);
+      DiagonalMatrix D = IM;
+      LinearEquationSolver LES2(IM);
+      LTX = LES2.i() * LT;
+      M = LTX * 2 - LT; Print(M);
+      UpperTriangularMatrix UTX = LES1.i() * UT;
+      M = UTX * 2 - UT; Print(M);
+      UTX = LES2.i() * UT;
+      M = UTX * 2 - UT; Print(M);
+   }
+
+   {
+      Tracer et1("Stage 7");
+      // Some more GenericMatrix stuff with *= |= &=
+      // but don't any additional checks
+      BandMatrix BM1(6,2,3);
+      BM1.Row(1) << 3 << 8 << 4 << 1;
+      BM1.Row(2) << 5 << 1 << 9 << 7 << 2;
+      BM1.Row(3) << 1 << 0 << 6 << 3 << 1 << 3;
+      BM1.Row(4)      << 4 << 2 << 5 << 2 << 4;
+      BM1.Row(5)           << 3 << 3 << 9 << 1;
+      BM1.Row(6)                << 4 << 2 << 9;
+      BandMatrix BM2(6,1,1);
+      BM2.Row(1) << 2.5 << 7.5;
+      BM2.Row(2) << 1.5 << 3.0 << 8.5;
+      BM2.Row(3)        << 6.0 << 6.5 << 7.0;
+      BM2.Row(4)               << 2.5 << 2.0 << 8.0;
+      BM2.Row(5)                      << 0.5 << 4.5 << 3.5;
+      BM2.Row(6)                             << 9.5 << 7.5;
+      Matrix RM1 = BM1, RM2 = BM2;
+      Matrix X;
+      GenericMatrix GRM1 = RM1, GBM1 = BM1, GRM2 = RM2, GBM2 = BM2;
+      Matrix Z(6,0); Z = 5; Print(Z);
+      GRM1 |= Z; GBM1 |= Z; GRM2 &= Z.t(); GBM2 &= Z.t();
+      X = GRM1 - BM1; Print(X); X = GBM1 - BM1; Print(X);
+      X = GRM2 - BM2; Print(X); X = GBM2 - BM2; Print(X);
+
+      GRM1 = RM1; GBM1 = BM1; GRM2 = RM2; GBM2 = BM2;
+      GRM1 *= GRM2; GBM1 *= GBM2;
+      X = GRM1 - BM1 * BM2; Print(X);
+      X = RM1 * RM2 - GBM1; Print(X);
+
+      GRM1 = RM1; GBM1 = BM1; GRM2 = RM2; GBM2 = BM2;
+      GRM1 *= GBM2; GBM1 *= GRM2;          // Bs and Rs swapped on LHS
+      X = GRM1 - BM1 * BM2; Print(X);
+      X = RM1 * RM2 - GBM1; Print(X);
+
+      X = BM1.t(); BandMatrix BM1X = BM1.t();
+      GRM1 = RM1; X -= GRM1.t(); Print(X); X = BM1X - BM1.t(); Print(X);
+
+      // check that linear equation solver works with Identity Matrix
+      IdentityMatrix IM(6); IM *= 2;
+      GBM1 = BM1; GBM1 *= 4; GRM1 = RM1; GRM1 *= 4;
+      DiagonalMatrix D = IM;
+      LinearEquationSolver LES1(D);
+      BandMatrix BX;
+      BX = LES1.i() * GBM1; BX -= BM1 * 2; X = BX; Print(X);
+      LinearEquationSolver LES2(IM);
+      BX = LES2.i() * GBM1; BX -= BM1 * 2; X = BX; Print(X);
+      BX = D.i() * GBM1; BX -= BM1 * 2; X = BX; Print(X);
+      BX = IM.i() * GBM1; BX -= BM1 * 2; X = BX; Print(X);
+      BX = IM.i(); BX *= GBM1; BX -= BM1 * 2; X = BX; Print(X);
+
+      // try symmetric band matrices
+      SymmetricBandMatrix SBM; SBM << SP(BM1, BM1.t());
+      SBM << IM.i() * SBM;
+      X = 2 * SBM - SP(RM1, RM1.t()); Print(X);
+
+      // Do this again with more general D
+      D << 2.5 << 7.5 << 2 << 5 << 4.5 << 7.5;
+      BX = D.i() * BM1; X = BX - D.i() * RM1;
+      Clean(X,0.00000001); Print(X);
+      BX = D.i(); BX *= BM1; X = BX - D.i() * RM1;
+      Clean(X,0.00000001); Print(X);
+      SBM << SP(BM1, BM1.t());
+      BX = D.i() * SBM; X = BX - D.i() * SP(RM1, RM1.t());
+      Clean(X,0.00000001); Print(X);
+
+      // test return
+      BX = TestReturn(BM1); X = BX - BM1;
+      if (BX.BandWidth() != BM1.BandWidth()) X = 5;
+      Print(X);
+   }
+
+//   cout << "\nEnd of eighth test\n";
+}
Index: Shared/newmat/extra/tmt9.cpp
===================================================================
RCS file: Shared/newmat/extra/tmt9.cpp
diff -N Shared/newmat/extra/tmt9.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmt9.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,213 @@
+//#define WANT_STREAM
+
+#include "include.h"
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+void trymat9()
+{
+   Tracer et("Ninth test of Matrix package");
+   Tracer::PrintTrace();
+
+
+   int i; int j;
+   Matrix A(7,7); Matrix X(7,3);
+   for (i=1;i<=7;i++) for (j=1;j<=7;j++) A(i,j)=i*i+j+((i==j) ? 1 : 0);
+   for (i=1;i<=7;i++) for (j=1;j<=3;j++) X(i,j)=i-j;
+   Matrix B = A.i(); DiagonalMatrix D(7); D=1.0;
+   {
+      Tracer et1("Stage 1");
+      Matrix Q = B*A-D; Clean(Q, 0.000000001); Print(Q);
+      Q=A; Q = Q.i() * X; Q = A*Q - X; Clean(Q, 0.000000001); Print(Q);
+      Q=X; Q = A.i() * Q; Q = A*Q - X; Clean(Q, 0.000000001); Print(Q);
+   }
+   for (i=1;i<=7;i++) D(i,i)=i*i+1;
+   DiagonalMatrix E(3); for (i=1;i<=3;i++) E(i,i)=i+23;
+   {
+      Tracer et1("Stage 2");
+      Matrix DXE = D.i() * X * E;
+      DXE = E.i() * DXE.t() * D - X.t(); Clean(DXE, 0.00000001); Print(DXE); 
+      E=D; for (i=1;i<=7;i++) E(i,i)=i*3+1;
+   }
+   DiagonalMatrix F=D;
+   {
+      Tracer et1("Stage 3");
+      F=E.i()*F; F=F*E-D; Clean(F,0.00000001); Print(F);
+      F=E.i()*D; F=F*E-D; Clean(F,0.00000001); Print(F);
+   }
+   {
+      Tracer et1("Stage 4");
+      F=E; F=F.i()*D; F=F*E-D; Clean(F,0.00000001); Print(F);
+   }
+   {
+      Tracer et1("Stage 5");
+      // testing equal
+      ColumnVector A(18), B(18);
+      Matrix X(3,3);
+      X << 3 << 5  << 7 << 5 << 8 << 2 << 7 << 2 << 9;
+      SymmetricMatrix S; S << X;
+      B(1) = S == X;         A(1) = true;
+      B(2) = S == (X+1);     A(2) = false;
+      B(3) = (S+2) == (X+2); A(3) = true;
+      Matrix Y = X;
+      B(4) = X == Y;         A(4) = true;
+      B(5) = (X*2) == (Y*2); A(5) = true;
+      Y(3,3) = 10;
+      B(6) = X == Y;         A(6) = false;
+      B(7) = (X*2) == (Y*2); A(7) = false;
+      B(8) = S == Y;         A(8) = false;
+      B(9) = S == S;         A(9) = true;
+      Matrix Z = X.SubMatrix(1,2,2,3);
+      B(10) = X == Z;        A(10) = false;
+      GenericMatrix GS = S;
+      GenericMatrix GX = X;
+      GenericMatrix GY = Y;
+      B(11) = GS == GX;      A(11) = true;
+      B(12) = GS == GY;      A(12) = false;
+      CroutMatrix CS = S;
+      CroutMatrix CX = X;
+      CroutMatrix CY = Y;
+      B(13) = CS == CX;      A(13) = true;
+      B(14) = CS == CY;      A(14) = false;
+      B(15) = X == CX;       A(15) = false;
+      B(16) = X == A;        A(16) = false;
+      B(17) = X == (X | X);  A(17) = false;
+      B(18) = CX == X;       A(18) = false;
+      A = A - B; Print(A);
+   }
+   {
+      Tracer et1("Stage 6");
+      // testing equal
+      ColumnVector A(22), B(22);
+      BandMatrix X(6,2,1);
+      X(1,1)=23; X(1,2)=21;
+      X(2,1)=12; X(2,2)=17; X(2,3)=45;
+      X(3,1)=35; X(3,2)=19; X(3,3)=24; X(3,4)=29;
+                 X(4,2)=17; X(4,3)=11; X(4,4)=19; X(4,5)=35;
+                            X(5,3)=10; X(5,4)=44; X(5,5)=23; X(5,6)=31;
+                                       X(6,4)=49; X(6,5)=41; X(6,6)=17;
+      SymmetricBandMatrix S1(6,2); S1.Inject(X);
+      BandMatrix U(6,2,3); U = 0.0; U.Inject(X);
+      B(1) = U == X;         A(1) = true;
+      B(2) = U == (X*3);     A(2) = false;
+      B(3) = (U*5) == (X*5); A(3) = true;
+      Matrix Y = X;
+      B(4) = X == Y;         A(4) = true;
+      B(5) = (X*2) == (Y*2); A(5) = true;
+      Y(6,6) = 10;
+      B(6) = X == Y;         A(6) = false;
+      B(7) = (X*2) == (Y*2); A(7) = false;
+      B(8) = U == Y;         A(8) = false;
+      B(9) = U == U;         A(9) = true;
+      Matrix Z = X.SubMatrix(1,2,2,3);
+      B(10) = X == Z;        A(10) = false;
+      GenericMatrix GU = U;
+      GenericMatrix GX = X;
+      GenericMatrix GY = Y;
+      B(11) = GU == GX;      A(11) = true;
+      B(12) = GU == GY;      A(12) = false;
+      X = X + X.t(); U = U + U.t();
+      SymmetricBandMatrix S(6,2); S.Inject(X);
+      Matrix D = S-X; Print(D);
+      BandLUMatrix BS = S;
+      BandLUMatrix BX = X;
+      BandLUMatrix BU = U;
+      CroutMatrix CX = X;
+      B(13) = BS == BX;      A(13) = true;
+      B(14) = BX == BU;      A(14) = false;
+      B(15) = X == BX;       A(15) = false;
+      B(16) = X != BX;       A(16) = true;
+      B(17) = BX != BS;      A(17) = false;
+      B(18) = (2*X) != (X*2);A(18) = false;
+      B(19) = (X*2) != (X+2);A(19) = true;
+      B(20) = BX == CX;      A(20) = false;
+      B(21) = CX == BX;      A(21) = false;
+      B(22) = BX == X;       A(22) = false;
+      A = A - B; Print(A);
+      DiagonalMatrix I(6); I=1.0;
+      D = BS.i() * X - I;  Clean(D,0.00000001); Print(D);
+      D = BX.i() * X - I;  Clean(D,0.00000001); Print(D);
+      D = BU.i() * X - I;  Clean(D,0.00000001); Print(D);
+
+      // test row wise load
+      SymmetricBandMatrix X1(6,2);
+      X1.Row(1) << 23;
+      X1.Row(2) << 12 << 17;
+      X1.Row(3) << 35 << 19 << 24;
+      X1.Row(4)       << 17 << 11 << 19;
+      X1.Row(5)             << 10 << 44 << 23;
+      X1.Row(6)                   << 49 << 41 << 17;
+      Matrix M = X1 - S1; Print(M);
+
+      // check out submatrix
+      SymmetricBandMatrix X2(20,3); X2 = 0.0;
+      X2.SubMatrix(2,7,2,7) = X1; X2.SymSubMatrix(11,16) = 2 * X1;
+      Matrix MX1 = X1;
+      Matrix MX2(20,20); MX2 = 0;
+      MX2.SymSubMatrix(2,7) = MX1; MX2.SubMatrix(11,16,11,16) = MX1 * 2;
+      MX2 -= X2; Print(MX2);
+
+      BandMatrix X4(20,3,3); X4 = 0.0;
+      X4.SubMatrix(2,7,3,8) = X1; X4.SubMatrix(11,16,10,15) = 2 * X1;
+      MX1 = X1;
+      Matrix MX4(20,20); MX4 = 0;
+      MX4.SubMatrix(2,7,3,8) = MX1; MX4.SubMatrix(11,16,10,15) = MX1 * 2;
+      MX4 -= X4; Print(MX4);
+
+      MX1 = X1.i() * X1 - IdentityMatrix(6);
+      Clean(MX1,0.00000001); Print(MX1);
+
+   }
+
+   {
+      Tracer et1("Stage 7");
+      // testing equal
+      ColumnVector A(12), B(12);
+      BandMatrix X(6,2,1);
+      X(1,1)=23; X(1,2)=21;
+      X(2,1)=12; X(2,2)=17; X(2,3)=45;
+      X(3,1)=35; X(3,2)=19; X(3,3)=24; X(3,4)=29;
+                 X(4,2)=17; X(4,3)=11; X(4,4)=19; X(4,5)=35;
+                            X(5,3)=10; X(5,4)=44; X(5,5)=23; X(5,6)=31;
+                                       X(6,4)=49; X(6,5)=41; X(6,6)=17;
+      Matrix Y = X;
+      LinearEquationSolver LX = X;
+      LinearEquationSolver LY = Y;
+      CroutMatrix CX = X;
+      CroutMatrix CY = Y;
+      BandLUMatrix BX = X;
+      B(1) = LX == CX;       A(1) = false;
+      B(2) = LY == CY;       A(2) = true;
+      B(3) = X == Y;         A(3) = true;
+      B(4) = BX == LX;       A(4) = true;
+      B(5) = CX == CY;       A(5) = true;
+      B(6) = LX == LY;       A(6) = false;
+      B(7) = BX == BX;       A(7) = true;
+      B(8) = CX == CX;       A(8) = true;
+      B(9) = LX == LX;       A(9) = true;
+      B(10) = LY == LY;      A(10) = true;
+      CroutMatrix CX1 = X.SubMatrix(1,4,1,4);
+      B(11) = CX == CX1;     A(11) = false;
+      BandLUMatrix BX1 = X.SymSubMatrix(1,4);    // error with SubMatrix
+      B(12) = BX == BX1;     A(12) = false;
+      A = A - B; Print(A);
+      DiagonalMatrix I(6); I=1.0; Matrix D;
+      D = LX.i() * X - I;  Clean(D,0.00000001); Print(D);
+      D = LY.i() * X - I;  Clean(D,0.00000001); Print(D);
+      I.ReSize(4); I = 1;
+      D = CX1.i() * X.SymSubMatrix(1,4) - I;  Clean(D,0.00000001); Print(D);
+      D = BX1.i() * X.SubMatrix(1,4,1,4) - I;  Clean(D,0.00000001); Print(D);
+   }
+
+//   cout << "\nEnd of ninth test\n";
+}
+
Index: Shared/newmat/extra/tmta.cpp
===================================================================
RCS file: Shared/newmat/extra/tmta.cpp
diff -N Shared/newmat/extra/tmta.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmta.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,126 @@
+
+//#define WANT_STREAM
+
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+
+static void process(const GeneralMatrix& A,
+   const ColumnVector& X1, const ColumnVector& X2)
+{
+      Matrix B = A;
+      LinearEquationSolver L(A);
+      Matrix Y(4,2);
+      Y.Column(1) << L.i() * X1; Y.Column(2) << L.i() * X2;
+      Matrix Z(4,2); Z.Column(1) << X1; Z.Column(2) << X2;
+      Z = B * Y - Z; Clean(Z,0.00000001); Print(Z);
+}
+
+
+
+void trymata()
+{
+//   cout << "\nTenth test of Matrix package\n";
+   Tracer et("Tenth test of Matrix package");
+   Tracer::PrintTrace();
+   int i; int j;
+   UpperTriangularMatrix U(8);
+   for (i=1;i<=8;i++) for (j=i;j<=8;j++) U(i,j)=i+j*j+5;
+   Matrix X(8,6);
+   for (i=1;i<=8;i++) for (j=1;j<=6;j++) X(i,j)=i*j+1.0;
+   Matrix Y = U.i()*X; Matrix MU=U;
+   Y=Y-MU.i()*X; Clean(Y,0.00000001); Print(Y);
+   Y = U.t().i()*X; Y=Y-MU.t().i()*X; Clean(Y,0.00000001); Print(Y);
+   UpperTriangularMatrix UX(8);
+   for (i=1;i<=8;i++) for (j=i;j<=8;j++) UX(i,j)=i+j+1;
+   UX(4,4)=0; UX(4,5)=0;
+   UpperTriangularMatrix UY = U.i() * UX;
+   { X=UX; MU=U; Y=UY-MU.i()*X; Clean(Y,0.000000001); Print(Y); }
+   LowerTriangularMatrix LY = U.t().i() * UX.t();
+   { Y=LY-MU.i().t()*X.t(); Clean(Y,0.000000001); Print(Y); }
+   DiagonalMatrix D(8); for (i=1;i<=8;i++) D(i,i)=i+1;
+   { X=D.i()*MU; }
+   { UY=U; UY=D.i()*UY; Y=UY-X; Clean(Y,0.00000001); Print(Y); }
+   { UY=D.i()*U; Y=UY-X; Clean(Y,0.00000001); Print(Y); }
+//   X=MU.t();
+//   LY=D.i()*U.t(); Y=D*LY-X; Clean(Y,0.00000001); Print(Y);
+//   LowerTriangularMatrix L=U.t();
+//   LY=D.i()*L; Y=D*LY-X; Clean(Y,0.00000001); Print(Y);
+   U.ReSize(8);
+   for (i=1;i<=8;i++) for (j=i;j<=8;j++) U(i,j)=i+j*j+5;
+   MU = U;
+   MU = U.i() - MU.i(); Clean(MU,0.00000001); Print(MU);
+   MU = U.t().i() - U.i().t(); Clean(MU,0.00000001); Print(MU);
+
+   // test LINEQ
+   {
+      ColumnVector X1(4), X2(4);
+      X1(1)=1; X1(2)=2; X1(3)=3; X1(4)=4;
+      X2(1)=1; X2(2)=10; X2(3)=100; X2(4)=1000;
+
+
+      Matrix A(4,4);
+      A(1,1)=1; A(1,2)=3; A(1,3)=0; A(1,4)=0;
+      A(2,1)=3; A(2,2)=2; A(2,3)=5; A(2,4)=0;
+      A(3,1)=0; A(3,2)=5; A(3,3)=4; A(3,4)=1;
+      A(4,1)=0; A(4,2)=0; A(4,3)=1; A(4,4)=3;
+      process(A,X1,X2);
+
+      BandMatrix B(4,1,1);  B.Inject(A);
+      process(B,X1,X2);
+
+      UpperTriangularMatrix U(4);
+      U(1,1)=1; U(1,2)=2; U(1,3)=3; U(1,4)=4;
+		U(2,2)=8; U(2,3)=7; U(2,4)=6;
+			  U(3,3)=2; U(3,4)=7;
+				    U(4,4)=1;
+      process(U,X1,X2);
+
+      // check rowwise load
+      UpperTriangularMatrix U1(4);
+      U1.Row(1) << 1 << 2 << 3 << 4;
+      U1.Row(2)      << 8 << 7 << 6;
+      U1.Row(3)           << 2 << 7;
+      U1.Row(4)                << 1;
+
+      U1 -= U;
+
+      Print(U1);
+
+      LowerTriangularMatrix L = U.t();
+      process(L,X1,X2);
+   }
+
+   // test inversion of poorly conditioned matrix
+   // a user complained this didn't work under OS9
+   {
+      Matrix M(4,4);
+
+      M <<  8.613057e+00 <<  8.693985e+00 << -2.322050e-01  << 0.000000e+00
+        <<  8.693985e+00 <<  8.793868e+00 << -2.346310e-01  << 0.000000e+00
+        << -2.322050e-01 << -2.346310e-01 <<  6.264000e-03  << 0.000000e+00
+        <<  0.000000e+00 <<  0.000000e+00 <<  0.000000e+00  << 3.282806e+03 ;
+      Matrix MI = M.i();
+      DiagonalMatrix I(4); I = 1;
+      Matrix Diff = MI *  M - I;
+      Clean(Diff,0.00000001); Print(Diff);
+      // Alternatively do Cholesky
+      SymmetricMatrix SM; SM << M;
+      LowerTriangularMatrix LT = Cholesky(SM).i();
+      MI = LT.t() * LT; Diff = MI *  M - I;
+      Clean(Diff,0.00000001); Print(Diff);
+   }
+
+//   cout << "\nEnd of tenth test\n";
+}
Index: Shared/newmat/extra/tmtb.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtb.cpp
diff -N Shared/newmat/extra/tmtb.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtb.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,152 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+/**************************** test program ******************************/
+
+// make sure matrices work as members of a class
+
+class TestClass
+{
+   Matrix A;
+   Matrix B;
+public:
+   TestClass();
+   ReturnMatrix Sum();
+};
+
+TestClass::TestClass() : A(2,3)
+{
+   B.ReSize(2,3);
+   A << 1 << 4
+     << 4 << 1
+     << 2 << 9;
+   B << 8 << 5
+     << 5 << 8
+     << 7 << 0;
+}
+
+ReturnMatrix TestClass::Sum() { return Matrix(A + B).ForReturn(); }
+
+
+
+void trymatb()
+{
+//   cout << "\nEleventh test of Matrix package\n";
+   Tracer et("Eleventh test of Matrix package");
+   Tracer::PrintTrace();
+   int i; int j;
+   RowVector RV; RV.ReSize(10);
+   {
+      Tracer et1("Stage 1");
+      for (i=1;i<=10;i++) RV(i)=i*i-3;
+      Matrix X(1,1); X(1,1) = .25;
+      Print(RowVector(X.i() * RV - RV / .25));
+//      Print(RowVector(X.i() * Matrix(RV) - RV / .25)); // != zortech, AT&T
+      Print(RowVector(X.i() * RV - RV / .25));
+   }
+   LowerTriangularMatrix L(5); UpperTriangularMatrix U(5);
+   for (i=1; i<=5; i++) for (j=1; j<=i; j++)
+   { L(i,j) = i*i + j -2.0; U(j,i) = i*i*j+3; }
+   DiagonalMatrix D(5);
+   for (i=1; i<=5; i++) D(i,i) = i*i + i + 2;
+   Matrix M1 = -L; Matrix M2 = L-U; Matrix M3 = U*3; Matrix M4 = U-L;
+   Matrix M5 = M1 - D; M1 = D * (-3) - M3;
+   {
+      Tracer et1("Stage 2");
+      Print(Matrix((M2-M4*2)+M5*3-M1));
+      M1 = L.t(); Print(Matrix(M1.t()-L));
+      M1 = U.t(); Print(Matrix(M1.t()-U));
+   }
+   {
+      Tracer et1("Stage 3");
+      SymmetricMatrix S(5);
+      for (i=1; i<=5; i++) for (j=1; j<=i; j++) S(i,j) = i*j+i-j+5;
+      M2 = S.i() * M4; M1 = S; M3=M1*M2-M4; Clean(M3,0.00000001); Print(M3);
+      SymmetricMatrix T(5);
+      for (i=1; i<=5; i++) for (j=1; j<=i; j++) T(i,j) = i*i*j*j+i-j+5-i*j;
+      M1 = S.i() * T; M1 = S * M1; M1 = M1-T; Clean(M1,0.00000001); Print(M1);
+      ColumnVector CV(5); for (i=1; i<=5; i++) CV(i) = i*i*i+10;
+      M1 = CV * RV;
+   }
+   {
+      Tracer et1("Stage 4");
+      M4.ReSize(5,10);
+      for (i=1; i<=5; i++) for (j=1; j<=10; j++) M4(i,j) = (i*i*i+10)*(j*j-3);
+      Print(Matrix(M1-M4));
+      M1 = L.t(); M2 = U.t(); M3 = L+U; Print(Matrix(M1-M3.t()+M2));
+   }
+//   UpperTriangularMatrix U2((const UpperTriangularMatrix&)U); // != zortech
+   UpperTriangularMatrix U2((UpperTriangularMatrix&)U);
+   {
+      Tracer et1("Stage 5");
+      Print(Matrix(U2-U));
+      M2.ReSize(10,10);
+      for (i=1; i<=10; i++) for (j=1; j<=10; j++) M2(i,j) = (i*i*i+10)*(j*j-3);
+      D << M2; L << M2; U << M2;               // check copy into
+      Print( Matrix( (D+M2)-(L+U) ) );
+   }
+   {
+      Tracer et1("Stage 6");
+      M1.ReSize(6,10);
+      for (i=1; i<=6; i++) for (j=1; j<=10; j++)  M1(i,j) = 100*i + j;
+      M2 = M1.SubMatrix(3,5,4,7);  M3.ReSize(3,4);
+      for (i=3; i<=5; i++) for (j=4; j<=7; j++)   M3(i-2,j-3) = 100*i + j;
+      Print(Matrix(M2-M3));
+   }
+   int a1,a2,a3,a4;
+   {
+      Tracer et1("Stage 7");
+      int a1,a2,a3,a4;
+      a1=4; a2=9; a3=4; a4=7;
+      U.ReSize(10);
+      for (i=1; i<=10; i++) for (j=i; j<=10; j++)  U(i,j) = 100*i + j;
+      M2 = U.SubMatrix(a1,a2,a3,a4);
+      M3.ReSize(a2-a1+1,a4-a3+1); M3=0.0;
+      for (i=a1; i<=a2; i++) for (j=(i>a3) ? i : a3; j<=a4; j++)
+         M3(i-a1+1,j-a3+1) = 100*i + j;
+      Print(Matrix(M2-M3));
+   }
+   {
+      Tracer et1("Stage 8");
+      a1=3; a2=9; a3=2; a4=7;
+      U.ReSize(10);
+      for (i=1; i<=10; i++) for (j=i; j<=10; j++)  U(i,j) = 100*i + j;
+      M2 = U.SubMatrix(a1,a2,a3,a4);
+      M3.ReSize(a2-a1+1,a4-a3+1); M3=0.0;
+      for (i=a1; i<=a2; i++) for (j=(i>a3) ? i : a3; j<=a4; j++)
+         M3(i-a1+1,j-a3+1) = 100*i + j;
+      Print(Matrix(M2-M3));
+   }
+   {
+      Tracer et1("Stage 9");
+      a1=4; a2=6; a3=2; a4=5;
+      U.ReSize(10);
+      for (i=1; i<=10; i++) for (j=i; j<=10; j++)  U(i,j) = 100*i + j;
+      M2 = U.SubMatrix(a1,a2,a3,a4);
+      M3.ReSize(a2-a1+1,a4-a3+1); M3=0.0;
+      for (i=a1; i<=a2; i++) for (j=(i>a3) ? i : a3; j<=a4; j++)
+         M3(i-a1+1,j-a3+1) = 100*i + j;
+      Print(Matrix(M2-M3));
+   }
+
+   {
+      Tracer et1("Stage 10");
+      TestClass TC;
+      Matrix M = TC.Sum() - 9;
+      Print(M);
+   }
+
+
+//   cout << "\nEnd of eleventh test\n";
+}
Index: Shared/newmat/extra/tmtc.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtc.cpp
diff -N Shared/newmat/extra/tmtc.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtc.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,203 @@
+
+//#define WANT_STREAM
+
+
+#include "include.h"
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+
+void trymatc()
+{
+//   cout << "\nTwelfth test of Matrix package\n";
+   Tracer et("Twelfth test of Matrix package");
+   Tracer::PrintTrace();
+   DiagonalMatrix D(15); D=1.5;
+   Matrix A(15,15);
+   int i,j;
+   for (i=1;i<=15;i++) for (j=1;j<=15;j++) A(i,j)=i*i+j-150;
+   { A = A + D; }
+   ColumnVector B(15);
+   for (i=1;i<=15;i++) B(i)=i+i*i-150.0;
+   {
+      Tracer et1("Stage 1");
+      ColumnVector B1=B;
+      B=(A*2.0).i() * B1;
+      Matrix X = A*B-B1/2.0;
+      Clean(X, 0.000000001); Print(X);
+      A.ReSize(3,5);
+      for (i=1; i<=3; i++) for (j=1; j<=5; j++) A(i,j) = i+100*j;
+
+      B = A.AsColumn()+10000;
+      RowVector R = (A+10000).AsColumn().t();
+      Print( RowVector(R-B.t()) );
+   }
+
+   {
+      Tracer et1("Stage 2");
+      B = A.AsColumn()+10000;
+      Matrix XR = (A+10000).AsMatrix(15,1).t();
+      Print( RowVector(XR-B.t()) );
+   }
+
+   {
+      Tracer et1("Stage 3");
+      B = (A.AsMatrix(15,1)+A.AsColumn())/2.0+10000;
+      Matrix MR = (A+10000).AsColumn().t();
+      Print( RowVector(MR-B.t()) );
+
+      B = (A.AsMatrix(15,1)+A.AsColumn())/2.0;
+      MR = A.AsColumn().t();
+      Print( RowVector(MR-B.t()) );
+   }
+
+   {
+      Tracer et1("Stage 4");
+      B = (A.AsMatrix(15,1)+A.AsColumn())/2.0;
+      RowVector R = A.AsColumn().t();
+      Print( RowVector(R-B.t()) );
+   }
+
+   {
+      Tracer et1("Stage 5");
+      RowVector R = (A.AsColumn()-5000).t();
+      B = ((R.t()+10000) - A.AsColumn())-5000;
+      Print( RowVector(B.t()) );
+   }
+
+   {
+      Tracer et1("Stage 6");
+      B = A.AsColumn(); ColumnVector B1 = (A+10000).AsColumn() - 10000;
+      Print(ColumnVector(B1-B));
+   }
+
+   {
+      Tracer et1("Stage 7");
+      Matrix X = B.AsMatrix(3,5); Print(Matrix(X-A));
+      for (i=1; i<=3; i++) for (j=1; j<=5; j++) B(5*(i-1)+j) -= i+100*j;
+      Print(B);
+   }
+
+   {
+      Tracer et1("Stage 8");
+      A.ReSize(7,7); D.ReSize(7);
+      for (i=1; i<=7; i++) for (j=1; j<=7; j++) A(i,j) = i*j*j;
+      for (i=1; i<=7; i++) D(i,i) = i;
+      UpperTriangularMatrix U; U << A;
+      Matrix X = A; for (i=1; i<=7; i++) X(i,i) = i;
+      A.Inject(D); Print(Matrix(X-A));
+      X = U; U.Inject(D); A = U; for (i=1; i<=7; i++) X(i,i) = i;
+      Print(Matrix(X-A));
+   }
+
+   {
+      Tracer et1("Stage 9");
+      A.ReSize(7,5);
+      for (i=1; i<=7; i++) for (j=1; j<=5; j++) A(i,j) = i+100*j;
+      Matrix Y = A; Y = Y - ((const Matrix&)A); Print(Y);
+      Matrix X = A;
+      Y = A; Y = ((const Matrix&)X) - A; Print(Y); Y = 0.0;
+      Y = ((const Matrix&)X) - ((const Matrix&)A); Print(Y);
+   }
+
+   {
+      Tracer et1("Stage 10");
+      // some tests on submatrices
+      UpperTriangularMatrix U(20);
+      for (i=1; i<=20; i++) for (j=i; j<=20; j++) U(i,j)=100 * i + j;
+      UpperTriangularMatrix V = U.SymSubMatrix(1,5);
+      UpperTriangularMatrix U1 = U;
+      U1.SubMatrix(4,8,5,9) /= 2;
+      U1.SubMatrix(4,8,5,9) += 388 * V;
+      U1.SubMatrix(4,8,5,9) *= 2;
+      U1.SubMatrix(4,8,5,9) += V;
+      U1 -= U; UpperTriangularMatrix U2 = U1;
+      U1 << U1.SubMatrix(4,8,5,9);
+      U2.SubMatrix(4,8,5,9) -= U1; Print(U2);
+      U1 -= (777*V); Print(U1);
+
+      U1 = U; U1.SubMatrix(4,8,5,9) -= U.SymSubMatrix(1,5);
+      U1 -= U;  U2 = U1; U1 << U1.SubMatrix(4,8,5,9);
+      U2.SubMatrix(4,8,5,9) -= U1; Print(U2);
+      U1 += V; Print(U1);
+
+      U1 = U;
+      U1.SubMatrix(3,10,15,19) += 29;
+      U1 -= U;
+      Matrix X = U1.SubMatrix(3,10,15,19); X -= 29; Print(X);
+      U1.SubMatrix(3,10,15,19) *= 0; Print(U1);
+
+      LowerTriangularMatrix L = U.t();
+      LowerTriangularMatrix M = L.SymSubMatrix(1,5);
+      LowerTriangularMatrix L1 = L;
+      L1.SubMatrix(5,9,4,8) /= 2;
+      L1.SubMatrix(5,9,4,8) += 388 * M;
+      L1.SubMatrix(5,9,4,8) *= 2;
+      L1.SubMatrix(5,9,4,8) += M;
+      L1 -= L; LowerTriangularMatrix L2 = L1;
+      L1 << L1.SubMatrix(5,9,4,8);
+      L2.SubMatrix(5,9,4,8) -= L1; Print(L2);
+      L1 -= (777*M); Print(L1);
+
+      L1 = L; L1.SubMatrix(5,9,4,8) -= L.SymSubMatrix(1,5);
+      L1 -= L; L2 =L1; L1 << L1.SubMatrix(5,9,4,8);
+      L2.SubMatrix(5,9,4,8) -= L1; Print(L2);
+      L1 += M; Print(L1);
+
+      L1 = L;
+      L1.SubMatrix(15,19,3,10) -= 29;
+      L1 -= L;
+      X = L1.SubMatrix(15,19,3,10); X += 29; Print(X);
+      L1.SubMatrix(15,19,3,10) *= 0; Print(L1);
+   }
+
+   {
+      Tracer et1("Stage 11");
+      // more tests on submatrices
+      Matrix M(20,30);
+      for (i=1; i<=20; i++) for (j=1; j<=30; j++) M(i,j)=100 * i + j;
+      Matrix M1 = M;
+
+      for (j=1; j<=30; j++)
+         { ColumnVector CV = 3 * M1.Column(j); M.Column(j) += CV; }
+      for (i=1; i<=20; i++)
+         { RowVector RV = 5 * M1.Row(i); M.Row(i) -= RV; }
+
+      M += M1; Print(M);
+ 
+   }
+
+   {
+      Tracer et1("Stage 12");
+      // more tests on Release
+      Matrix M(20,30);
+      for (i=1; i<=20; i++) for (j=1; j<=30; j++) M(i,j)=100 * i + j;
+      Matrix M1 = M;
+      M.Release();
+      Matrix M2 = M;
+      Matrix X = M;   Print(X);
+      X = M1 - M2;    Print(X);
+
+#ifndef DONT_DO_NRIC
+      nricMatrix N = M1;
+      nricMatrix N1 = N;
+      N.Release();
+      nricMatrix N2 = N;
+      nricMatrix Y = N;   Print(Y);
+      Y = N1 - N2;        Print(Y);
+      
+      N = M1 / 2; N1 = N * 2; N.Release(); N2 = N * 2; Y = N; Print(N);
+      Y = (N1 - M1) | (N2 - M1); Print(Y);
+#endif
+
+   }
+
+//   cout << "\nEnd of twelfth test\n";
+}
Index: Shared/newmat/extra/tmtd.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtd.cpp
diff -N Shared/newmat/extra/tmtd.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtd.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,331 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+ReturnMatrix Inverter(const CroutMatrix& X)
+{
+   Matrix Y = X.i();
+   Y.Release();
+   return Y.ForReturn();
+}
+
+void CircularShift(const Matrix& X1, int first, int last)
+{
+      Matrix X; UpperTriangularMatrix U1, U2;
+      int n = X1.Ncols();
+
+      // Try right circular shift of columns
+      X = X1; QRZ(X, U1);
+      RightCircularUpdateCholesky(U1, first, last);
+      X = X1.Columns(1,first-1) | X1.Column(last)
+         | X1.Columns(first,last-1) | X1.Columns(last+1,n);
+      QRZ(X, U2);
+      X = U1 - U2; Clean(X, 0.000000001); Print(X);
+
+      // Try left circular shift of columns
+      X = X1; QRZ(X, U1);
+      LeftCircularUpdateCholesky(U1, first, last);
+      X = X1.Columns(1,first-1) | X1.Columns(first+1,last)
+         | X1.Column(first) | X1.Columns(last+1,n);
+      QRZ(X, U2);
+      X = U1 - U2; Clean(X, 0.000000001); Print(X);
+}
+
+class TestUpdateQRZ
+{
+   int m,n1,n2,n3;
+   Matrix X1, X2, X3;
+   MultWithCarry mwc;   // Uniform random number generator
+public:
+   void Reset();
+   TestUpdateQRZ(int mx, int n1x, int n2x=0, int n3x=0)
+      : m(mx), n1(n1x), n2(n2x), n3(n3x) { Reset(); }
+   void DoTest();
+   void ClearRow(int i)       { X1.Row(i) = 0.0; }
+   void SetRow(int i, int j)  { X1.Row(i) = X1.Row(j); }
+};
+
+
+
+void trymatd()
+{
+   Tracer et("Thirteenth test of Matrix package");
+   Tracer::PrintTrace();
+   Matrix X(5,20);
+   int i,j;
+   for (j=1;j<=20;j++) X(1,j) = j+1;
+   for (i=2;i<=5;i++) for (j=1;j<=20; j++) X(i,j) = (long)X(i-1,j) * j % 1001;
+   SymmetricMatrix S; S << X * X.t();
+   Matrix SM = X * X.t() - S;
+   Print(SM);
+   LowerTriangularMatrix L = Cholesky(S);
+   Matrix Diff = L*L.t()-S; Clean(Diff, 0.000000001);
+   Print(Diff);
+   {
+      Tracer et1("Stage 1");
+      LowerTriangularMatrix L1(5);
+      Matrix Xt = X.t(); Matrix Xt2 = Xt;
+      QRZT(X,L1);
+      Diff = L - L1; Clean(Diff,0.000000001); Print(Diff);
+      UpperTriangularMatrix Ut(5);
+      QRZ(Xt,Ut);
+      Diff = L - Ut.t(); Clean(Diff,0.000000001); Print(Diff);
+      Matrix Y(3,20);
+      for (j=1;j<=20;j++) Y(1,j) = 22-j;
+      for (i=2;i<=3;i++) for (j=1;j<=20; j++)
+         Y(i,j) = (long)Y(i-1,j) * j % 101;
+      Matrix Yt = Y.t(); Matrix M,Mt; Matrix Y2=Y;
+      QRZT(X,Y,M); QRZ(Xt,Yt,Mt);
+      Diff = Xt - X.t(); Clean(Diff,0.000000001); Print(Diff);
+      Diff = Yt - Y.t(); Clean(Diff,0.000000001); Print(Diff);
+      Diff = Mt - M.t(); Clean(Diff,0.000000001); Print(Diff);
+      Diff = Y2 * Xt2 * S.i() - M * L.i();
+      Clean(Diff,0.000000001); Print(Diff);
+   }
+
+   ColumnVector C1(5);
+   {
+      Tracer et1("Stage 2");
+      X.ReSize(5,5);
+      for (j=1;j<=5;j++) X(1,j) = j+1;
+      for (i=2;i<=5;i++) for (j=1;j<=5; j++)
+         X(i,j) = (long)X(i-1,j) * j % 1001;
+      for (i=1;i<=5;i++) C1(i) = i*i;
+      CroutMatrix A = X;
+      ColumnVector C2 = A.i() * C1; C1 = X.i()  * C1;
+      X = C1 - C2; Clean(X,0.000000001); Print(X);
+   }
+
+   {
+      Tracer et1("Stage 3");
+      X.ReSize(7,7);
+      for (j=1;j<=7;j++) X(1,j) = j+1;
+      for (i=2;i<=7;i++) for (j=1;j<=7; j++)
+         X(i,j) = (long)X(i-1,j) * j % 1001;
+      C1.ReSize(7);
+      for (i=1;i<=7;i++) C1(i) = i*i;
+      RowVector R1 = C1.t();
+      Diff = R1 * X.i() - ( X.t().i() * R1.t() ).t(); Clean(Diff,0.000000001);
+      Print(Diff);
+   }
+
+   {
+      Tracer et1("Stage 4");
+      X.ReSize(5,5);
+      for (j=1;j<=5;j++) X(1,j) = j+1;
+      for (i=2;i<=5;i++) for (j=1;j<=5; j++)
+         X(i,j) = (long)X(i-1,j) * j % 1001;
+      C1.ReSize(5);
+      for (i=1;i<=5;i++) C1(i) = i*i;
+      CroutMatrix A1 = X*X;
+      ColumnVector C2 = A1.i() * C1; C1 = X.i()  * C1; C1 = X.i()  * C1;
+      X = C1 - C2; Clean(X,0.000000001); Print(X);
+   }
+
+
+   {
+      Tracer et1("Stage 5");
+      int n = 40;
+      SymmetricBandMatrix B(n,2); B = 0.0;
+      for (i=1; i<=n; i++)
+      {
+         B(i,i) = 6;
+         if (i<=n-1) B(i,i+1) = -4;
+         if (i<=n-2) B(i,i+2) = 1;
+      }
+      B(1,1) = 5; B(n,n) = 5;
+      SymmetricMatrix A = B;
+      ColumnVector X(n);
+      X(1) = 429;
+      for (i=2;i<=n;i++) X(i) = (long)X(i-1) * 31 % 1001;
+      X = X / 100000L;
+      // the matrix B is rather ill-conditioned so the difficulty is getting
+      // good agreement (we have chosen X very small) may not be surprising;
+      // maximum element size in B.i() is around 1400
+      ColumnVector Y1 = A.i() * X;
+      LowerTriangularMatrix C1 = Cholesky(A);
+      ColumnVector Y2 = C1.t().i() * (C1.i() * X) - Y1;
+      Clean(Y2, 0.000000001); Print(Y2);
+      UpperTriangularMatrix CU = C1.t().i();
+      LowerTriangularMatrix CL = C1.i();
+      Y2 = CU * (CL * X) - Y1;
+      Clean(Y2, 0.000000001); Print(Y2);
+      Y2 = B.i() * X - Y1; Clean(Y2, 0.000000001); Print(Y2);
+
+      LowerBandMatrix C2 = Cholesky(B);
+      Matrix M = C2 - C1; Clean(M, 0.000000001); Print(M);
+      ColumnVector Y3 = C2.t().i() * (C2.i() * X) - Y1;
+      Clean(Y3, 0.000000001); Print(Y3);
+      CU = C1.t().i();
+      CL = C1.i();
+      Y3 = CU * (CL * X) - Y1;
+      Clean(Y3, 0.000000001); Print(Y3);
+
+      Y3 = B.i() * X - Y1; Clean(Y3, 0.000000001); Print(Y3);
+
+      SymmetricMatrix AI = A.i();
+      Y2 = AI*X - Y1; Clean(Y2, 0.000000001); Print(Y2);
+      SymmetricMatrix BI = B.i();
+      BandMatrix C = B; Matrix CI = C.i();
+      M = A.i() - CI; Clean(M, 0.000000001); Print(M);
+      M = B.i() - CI; Clean(M, 0.000000001); Print(M);
+      M = AI-BI; Clean(M, 0.000000001); Print(M);
+      M = AI-CI; Clean(M, 0.000000001); Print(M);
+
+      M = A; AI << M; M = AI-A; Clean(M, 0.000000001); Print(M);
+      C = B; BI << C; M = BI-B; Clean(M, 0.000000001); Print(M);
+   }
+
+   {
+      Tracer et1("Stage 5");
+      SymmetricMatrix A(4), B(4);
+      A << 5
+        << 1 << 4
+        << 2 << 1 << 6
+        << 1 << 0 << 1 << 7;
+      B << 8
+        << 1 << 5
+        << 1 << 0 << 9
+        << 2 << 1 << 0 << 6;
+      LowerTriangularMatrix AB = Cholesky(A) * Cholesky(B);
+      Matrix M = Cholesky(A) * B * Cholesky(A).t() - AB*AB.t();
+      Clean(M, 0.000000001); Print(M);
+      M = A * Cholesky(B); M = M * M.t() - A * B * A;
+      Clean(M, 0.000000001); Print(M);
+   }
+   
+   {
+      Tracer et1("Stage 6");
+      int N=49;
+      int i;
+      SymmetricBandMatrix S(N,1);
+      Matrix B(N,N+1); B=0;
+      for (i=1;i<=N;i++) { S(i,i)=1; B(i,i)=1; B(i,i+1)=-1; }
+      for (i=1;i<N; i++) S(i,i+1)=-.5;
+      DiagonalMatrix D(N+1); D = 1;
+      B = B.t()*S.i()*B - (D-1.0/(N+1))*2.0;
+      Clean(B, 0.000000001); Print(B);
+   }
+   {
+      Tracer et1("Stage 7");
+      // See if you can pass a CroutMatrix to a function
+      Matrix A(4,4);
+      A.Row(1) <<  3 <<  2 << -1 <<  4;
+      A.Row(2) << -8 <<  7 <<  2 <<  0;
+      A.Row(3) <<  2 << -2 <<  3 <<  1;
+      A.Row(4) << -1 <<  5 <<  2 <<  2;
+      CroutMatrix B = A;
+      Matrix C = A * Inverter(B) - IdentityMatrix(4);
+      Clean(C, 0.000000001); Print(C);
+   }
+
+   {
+      Tracer et1("Stage 8");
+      // Modification of Cholesky decomposition
+
+      int i, j;
+
+      // Build test matrix
+      Matrix X(100, 10);
+      MultWithCarry mwc;   // Uniform random number generator
+      for (i = 1; i <= 100; ++i) for (j = 1; j <= 10; ++j)
+         X(i, j) = 2.0 * (mwc.Next() - 0.5);
+      Matrix X1 = X;     // save copy
+
+      // Form sums of squares and products matrix and Cholesky decompose
+      SymmetricMatrix A; A << X.t() * X;
+      UpperTriangularMatrix U1 = Cholesky(A).t();
+
+      // Do QR decomposition of X and check we get same triangular matrix
+      UpperTriangularMatrix U2;
+      QRZ(X, U2);
+      Matrix Diff = U1 - U2; Clean(Diff, 0.000000001); Print(Diff);
+
+      // Try adding new row to X and updating triangular matrix 
+      RowVector NewRow(10);
+      for (j = 1; j <= 10; ++j) NewRow(j) = 2.0 * (mwc.Next() - 0.5);
+      UpdateCholesky(U2, NewRow);
+      X = X1 & NewRow; QRZ(X, U1);
+      Diff = U1 - U2; Clean(Diff, 0.000000001); Print(Diff);
+
+      // Try removing two rows and updating triangular matrix
+      DowndateCholesky(U2, X1.Row(20));
+      DowndateCholesky(U2, X1.Row(35));
+      X = X1.Rows(1,19) & X1.Rows(21,34) & X1.Rows(36,100) & NewRow; QRZ(X, U1);
+      Diff = U1 - U2; Clean(Diff, 0.000000001); Print(Diff);
+
+      // Circular shifts
+
+      CircularShift(X, 3,6);
+      CircularShift(X, 5,5);
+      CircularShift(X, 4,5);
+      CircularShift(X, 1,6);
+      CircularShift(X, 6,10);
+   }
+   
+   {
+      Tracer et1("Stage 9");
+      // Try updating QRZ, QRZT decomposition
+      TestUpdateQRZ tuqrz1(10, 100, 50, 25); tuqrz1.DoTest();
+      tuqrz1.Reset(); tuqrz1.ClearRow(1); tuqrz1.DoTest();
+      tuqrz1.Reset(); tuqrz1.ClearRow(1); tuqrz1.ClearRow(2); tuqrz1.DoTest();
+      tuqrz1.Reset(); tuqrz1.ClearRow(5); tuqrz1.ClearRow(6); tuqrz1.DoTest();
+      tuqrz1.Reset(); tuqrz1.ClearRow(10); tuqrz1.DoTest();
+      TestUpdateQRZ tuqrz2(15, 100, 0, 0); tuqrz2.DoTest();
+      tuqrz2.Reset(); tuqrz2.ClearRow(1); tuqrz2.DoTest();
+      tuqrz2.Reset(); tuqrz2.ClearRow(1); tuqrz2.ClearRow(2); tuqrz2.DoTest();
+      tuqrz2.Reset(); tuqrz2.ClearRow(5); tuqrz2.ClearRow(6); tuqrz2.DoTest();
+      tuqrz2.Reset(); tuqrz2.ClearRow(15); tuqrz2.DoTest();
+      TestUpdateQRZ tuqrz3(5, 0, 10, 0); tuqrz3.DoTest();
+      
+   }
+   
+//   cout << "\nEnd of Thirteenth test\n";
+}
+
+void TestUpdateQRZ::Reset()
+{
+   int i, j;
+   // set up Matrices
+   X1.ReSize(m, n1); X2.ReSize(m, n2); X3.ReSize(m, n3);
+   for (i = 1; i <= m; ++i) for (j = 1; j <= n1; ++j)
+      X1(i, j) = 2.0 * (mwc.Next() - 0.5);
+   for (i = 1; i <= m; ++i) for (j = 1; j <= n2; ++j)
+      X2(i, j) = 2.0 * (mwc.Next() - 0.5);
+   for (i = 1; i <= m; ++i) for (j = 1; j <= n3; ++j)
+      X3(i, j) = 2.0 * (mwc.Next() - 0.5);
+}
+
+void TestUpdateQRZ::DoTest()
+{
+   Matrix XT1 = X1.t(), XT2 = X2.t(), XT3 = X3.t();
+   Matrix X = X1 | X2 | X3;
+   SymmetricMatrix SM; SM << X * X.t();
+   LowerTriangularMatrix L, LX, LY, L0;
+   QRZT(X, L);
+   X = X1 | X2 | X3;
+   LY.ReSize(m); LY = 0.0;
+   UpdateQRZT(X, LY);
+   QRZT(X1, LX); UpdateQRZT(X2, LX); UpdateQRZT(X3, LX);
+   Matrix Diff = L * L.t() - SM; Clean(Diff, 0.000000001); Print(Diff);
+   Diff = SM - LX * LX.t(); Clean(Diff, 0.000000001); Print(Diff);
+   Diff = SM - LY * LY.t(); Clean(Diff, 0.000000001); Print(Diff);
+   UpperTriangularMatrix U, UX, UY;
+   X = XT1 & XT2 & XT3;
+   QRZ(X, U);
+   Diff = U.t() * U - SM; Clean(Diff, 0.000000001); Print(Diff);
+   UY.ReSize(m); UY = 0.0;
+   X = XT1 & XT2 & XT3;
+   UpdateQRZ(X, UY);
+   Diff = SM - UY.t() * UY; Clean(Diff, 0.000000001); Print(Diff);
+   QRZ(XT1, UX); UpdateQRZ(XT2, UX); UpdateQRZ(XT3, UX);
+   Diff = SM - UX.t() * UX; Clean(Diff, 0.000000001); Print(Diff);
+}   
Index: Shared/newmat/extra/tmte.cpp
===================================================================
RCS file: Shared/newmat/extra/tmte.cpp
diff -N Shared/newmat/extra/tmte.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmte.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,483 @@
+
+//#define WANT_STREAM
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmatap.h"
+//#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+// check D is sorted
+void CheckIsSorted(const DiagonalMatrix& D, bool ascending = false)
+{
+   DiagonalMatrix D1 = D;
+   if (ascending) SortAscending(D1); else SortDescending(D1);
+   D1 -= D; Print(D1);
+}
+
+
+
+void trymate()
+{
+
+
+   Tracer et("Fourteenth test of Matrix package");
+   Tracer::PrintTrace();
+
+   {
+      Tracer et1("Stage 1");
+      Matrix A(8,5);
+      {
+         Real   a[] = { 22, 10,  2,  3,  7,
+                        14,  7, 10,  0,  8,
+                        -1, 13, -1,-11,  3,
+                        -3, -2, 13, -2,  4,
+                         9,  8,  1, -2,  4,
+                         9,  1, -7,  5, -1,
+                         2, -6,  6,  5,  1,
+                         4,  5,  0, -2,  2 };
+         int   ai[] = { 22, 10,  2,  3,  7,
+                        14,  7, 10,  0,  8,
+                        -1, 13, -1,-11,  3,
+                        -3, -2, 13, -2,  4,
+                         9,  8,  1, -2,  4,
+                         9,  1, -7,  5, -1,
+                         2, -6,  6,  5,  1,
+                         4,  5,  0, -2,  2 };
+         A << a;
+
+         Matrix AI(8,5);
+         AI << ai; AI -= A; Print(AI);
+         int b[] = { 13, -1,-11,
+                     -2, 13, -2,
+                      8,  1, -2,
+                      1, -7,  5 };
+         Matrix B(8, 5); B = 23;
+         B.SubMatrix(3,6,2,4) << b;
+         AI = A;
+         AI.Rows(1,2) = 23; AI.Rows(7,8) = 23;
+         AI.Column(1) = 23; AI.Column(5) = 23;
+         AI -= B; Print(AI);
+      }
+      DiagonalMatrix D; Matrix U; Matrix V;
+      int anc = A.Ncols(); IdentityMatrix I(anc);
+      SymmetricMatrix S1; S1 << A.t() * A;
+      SymmetricMatrix S2; S2 << A * A.t();
+      Real zero = 0.0; SVD(A+zero,D,U,V); CheckIsSorted(D);
+      DiagonalMatrix D1; SVD(A,D1); CheckIsSorted(D1);
+      Print(DiagonalMatrix(D-D1));
+      Matrix W;
+      SVD(A, D1, W, W, true, false); D1 -= D; W -= U;
+      Clean(W,0.000000001); Print(W); Clean(D1,0.000000001); Print(D1);
+      Matrix WX;
+      SVD(A, D1, WX, W, false, true); D1 -= D; W -= V;
+      Clean(W,0.000000001); Print(W); Clean(D1,0.000000001); Print(D1);
+      Matrix SU = U.t() * U - I; Clean(SU,0.000000001); Print(SU);
+      Matrix SV = V.t() * V - I; Clean(SV,0.000000001); Print(SV);
+      Matrix B = U * D * V.t() - A; Clean(B,0.000000001); Print(B);
+      D1=0.0;  SVD(A,D1,A); CheckIsSorted(D1); Print(Matrix(A-U));
+      D(1) -= sqrt(1248.0); D(2) -= 20; D(3) -= sqrt(384.0);
+      Clean(D,0.000000001); Print(D);
+
+      Jacobi(S1, D, V);  CheckIsSorted(D, true);
+      V = S1 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D = D.Reverse(); D(1)-=1248; D(2)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      Jacobi(S1, D);  CheckIsSorted(D, true);
+      D = D.Reverse(); D(1)-=1248; D(2)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      SymmetricMatrix JW(5);
+      Jacobi(S1, D, JW);  CheckIsSorted(D, true);
+      D = D.Reverse(); D(1)-=1248; D(2)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      Jacobi(S2, D, V);  CheckIsSorted(D, true);
+      V = S2 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D = D.Reverse(); D(1)-=1248; D(2)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      EigenValues(S1, D, V); CheckIsSorted(D, true);
+      V = S1 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D(5)-=1248; D(4)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      EigenValues(S2, D, V); CheckIsSorted(D, true);
+      V = S2 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D(8)-=1248; D(7)-=400; D(6)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      EigenValues(S1, D); CheckIsSorted(D, true);
+      D(5)-=1248; D(4)-=400; D(3)-=384;
+      Clean(D,0.000000001); Print(D);
+
+      SymmetricMatrix EW(S2);
+      EigenValues(S2, D, EW); CheckIsSorted(D, true);
+      D(8)-=1248; D(7)-=400; D(6)-=384;
+      Clean(D,0.000000001); Print(D);
+
+   }
+
+   {
+      Tracer et1("Stage 2");
+      Matrix A(20,21);
+      int i,j;
+      for (i=1; i<=20; i++) for (j=1; j<=21; j++)
+      { if (i>j) A(i,j) = 0; else if (i==j) A(i,j) = 21-i; else A(i,j) = -1; }
+      A = A.t();
+      SymmetricMatrix S1; S1 << A.t() * A;
+      SymmetricMatrix S2; S2 << A * A.t();
+      DiagonalMatrix D; Matrix U; Matrix V;
+      DiagonalMatrix I(A.Ncols());
+      I=1.0;
+      SVD(A,D,U,V); CheckIsSorted(D);
+      Matrix SU = U.t() * U - I;    Clean(SU,0.000000001); Print(SU);
+      Matrix SV = V.t() * V - I;    Clean(SV,0.000000001); Print(SV);
+      Matrix B = U * D * V.t() - A; Clean(B,0.000000001);  Print(B);
+      for (i=1; i<=20; i++)  D(i) -= sqrt((22.0-i)*(21.0-i));
+      Clean(D,0.000000001); Print(D);
+      Jacobi(S1, D, V); CheckIsSorted(D, true);
+      V = S1 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D = D.Reverse();
+      for (i=1; i<=20; i++)  D(i) -= (22-i)*(21-i);
+      Clean(D,0.000000001); Print(D);
+      Jacobi(S2, D, V); CheckIsSorted(D, true);
+      V = S2 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      D = D.Reverse();
+      for (i=1; i<=20; i++)  D(i) -= (22-i)*(21-i);
+      Clean(D,0.000000001); Print(D);
+
+      EigenValues(S1, D, V); CheckIsSorted(D, true);
+      V = S1 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      for (i=1; i<=20; i++)  D(i) -= (i+1)*i;
+      Clean(D,0.000000001); Print(D);
+      EigenValues(S2, D, V); CheckIsSorted(D, true);
+      V = S2 - V * D * V.t(); Clean(V,0.000000001); Print(V);
+      for (i=2; i<=21; i++)  D(i) -= (i-1)*i;
+      Clean(D,0.000000001); Print(D);
+
+      EigenValues(S1, D); CheckIsSorted(D, true);
+      for (i=1; i<=20; i++)  D(i) -= (i+1)*i;
+      Clean(D,0.000000001); Print(D);
+      EigenValues(S2, D); CheckIsSorted(D, true);
+      for (i=2; i<=21; i++)  D(i) -= (i-1)*i;
+      Clean(D,0.000000001); Print(D);
+   }
+
+   {
+      Tracer et1("Stage 3");
+      Matrix A(30,30);
+      int i,j;
+      for (i=1; i<=30; i++) for (j=1; j<=30; j++)
+      { if (i>j) A(i,j) = 0; else if (i==j) A(i,j) = 1; else A(i,j) = -1; }
+      Real d1 = A.LogDeterminant().Value();
+      DiagonalMatrix D; Matrix U; Matrix V;
+      DiagonalMatrix I(A.Ncols());
+      I=1.0;
+      SVD(A,D,U,V); CheckIsSorted(D);
+      Matrix SU = U.t() * U - I; Clean(SU,0.000000001); Print(SU);
+      Matrix SV = V.t() * V - I; Clean(SV,0.000000001); Print(SV);
+      Real d2 = D.LogDeterminant().Value();
+      Matrix B = U * D * V.t() - A; Clean(B,0.000000001); Print(B);
+      Real d3 = D.LogDeterminant().Value();
+      ColumnVector Test(3);
+      Test(1) = d1 - 1; Test(2) = d2 - 1; Test(3) = d3 - 1;
+      Clean(Test,0.00000001); Print(Test); // only 8 decimal figures
+      A.ReSize(2,2);
+      Real a = 1.5; Real b = 2; Real c = 2 * (a*a + b*b);
+      A << a << b << a << b;
+      I.ReSize(2); I=1;
+      SVD(A,D,U,V); CheckIsSorted(D);
+      SU = U.t() * U - I; Clean(SU,0.000000001); Print(SU);
+      SV = V.t() * V - I; Clean(SV,0.000000001); Print(SV);
+      B = U * D * V.t() - A; Clean(B,0.000000001); Print(B);
+      D = D*D; SortDescending(D);
+      DiagonalMatrix D50(2); D50 << c << 0; D = D - D50;
+      Clean(D,0.000000001);
+      Print(D);
+      A << a << a << b << b;
+      SVD(A,D,U,V); CheckIsSorted(D);
+      SU = U.t() * U - I; Clean(SU,0.000000001); Print(SU);
+      SV = V.t() * V - I; Clean(SV,0.000000001); Print(SV);
+      B = U * D * V.t() - A; Clean(B,0.000000001); Print(B);
+      D = D*D; SortDescending(D);
+      D = D - D50;
+      Clean(D,0.000000001);
+      Print(D);
+   }
+
+   {
+      Tracer et1("Stage 4");
+
+      // test for bug found by Olof Runborg,
+      // Department of Numerical Analysis and Computer Science (NADA),
+      // KTH, Stockholm
+
+      Matrix A(22,20);
+
+      A = 0;
+
+      int a=1;
+
+      A(a+0,a+2) = 1;     A(a+0,a+18) = -1;
+      A(a+1,a+9) = 1;     A(a+1,a+12) = -1;
+      A(a+2,a+11) = 1;    A(a+2,a+12) = -1;
+      A(a+3,a+10) = 1;    A(a+3,a+19) = -1;
+      A(a+4,a+16) = 1;    A(a+4,a+19) = -1;
+      A(a+5,a+17) = 1;    A(a+5,a+18) = -1;
+      A(a+6,a+10) = 1;    A(a+6,a+4) = -1;
+      A(a+7,a+3) = 1;     A(a+7,a+2) = -1;
+      A(a+8,a+14) = 1;    A(a+8,a+15) = -1;
+      A(a+9,a+13) = 1;    A(a+9,a+16) = -1;
+      A(a+10,a+8) = 1;    A(a+10,a+9) = -1;
+      A(a+11,a+1) = 1;    A(a+11,a+15) = -1;
+      A(a+12,a+16) = 1;   A(a+12,a+4) = -1;
+      A(a+13,a+6) = 1;    A(a+13,a+9) = -1;
+      A(a+14,a+5) = 1;    A(a+14,a+4) = -1;
+      A(a+15,a+0) = 1;    A(a+15,a+1) = -1;
+      A(a+16,a+14) = 1;   A(a+16,a+0) = -1;
+      A(a+17,a+7) = 1;    A(a+17,a+6) = -1;
+      A(a+18,a+13) = 1;   A(a+18,a+5) = -1;
+      A(a+19,a+7) = 1;    A(a+19,a+8) = -1;
+      A(a+20,a+17) = 1;   A(a+20,a+3) = -1;
+      A(a+21,a+6) = 1;    A(a+21,a+11) = -1;
+
+
+      Matrix U, V; DiagonalMatrix S;
+
+      SVD(A, S, U, V, true, true); CheckIsSorted(S);
+
+      DiagonalMatrix D(20); D = 1;
+
+      Matrix tmp = U.t() * U - D;
+      Clean(tmp,0.000000001); Print(tmp);
+
+      tmp = V.t() * V - D;
+      Clean(tmp,0.000000001); Print(tmp);
+
+      tmp = U * S * V.t() - A ;
+      Clean(tmp,0.000000001); Print(tmp);
+
+   }
+
+   {
+      Tracer et1("Stage 5");
+      Matrix A(10,10);
+
+      A.Row(1)  <<  1.00 <<  0.07 <<  0.05 <<  0.00 <<  0.06
+                <<  0.09 <<  0.03 <<  0.02 <<  0.02 << -0.03;
+      A.Row(2)  <<  0.07 <<  1.00 <<  0.05 <<  0.05 << -0.03
+                <<  0.07 <<  0.00 <<  0.07 <<  0.00 <<  0.02;
+      A.Row(3)  <<  0.05 <<  0.05 <<  1.00 <<  0.05 <<  0.02
+                <<  0.01 << -0.05 <<  0.04 <<  0.05 << -0.03;
+      A.Row(4)  <<  0.00 <<  0.05 <<  0.05 <<  1.00 << -0.05
+                <<  0.04 <<  0.01 <<  0.02 << -0.05 <<  0.00;
+      A.Row(5)  <<  0.06 << -0.03 <<  0.02 << -0.05 <<  1.00
+                << -0.03 <<  0.02 << -0.02 <<  0.04 <<  0.00;
+      A.Row(6)  <<  0.09 <<  0.07 <<  0.01 <<  0.04 << -0.03
+                <<  1.00 << -0.06 <<  0.08 << -0.02 << -0.10;
+      A.Row(7)  <<  0.03 <<  0.00 << -0.05 <<  0.01 <<  0.02
+                << -0.06 <<  1.00 <<  0.09 <<  0.12 << -0.03;
+      A.Row(8)  <<  0.02 <<  0.07 <<  0.04 <<  0.02 << -0.02
+                <<  0.08 <<  0.09 <<  1.00 <<  0.00 << -0.02;
+      A.Row(9)  <<  0.02 <<  0.00 <<  0.05 << -0.05 <<  0.04
+                << -0.02 <<  0.12 <<  0.00 <<  1.00 <<  0.02;
+      A.Row(10) << -0.03 <<  0.02 << -0.03 <<  0.00 <<  0.00
+                << -0.10 << -0.03 << -0.02 <<  0.02 <<  1.00;
+
+      SymmetricMatrix AS; AS << A;
+      Matrix V; DiagonalMatrix D, D1;
+      ColumnVector Check(6);
+      EigenValues(AS,D,V); CheckIsSorted(D, true);
+      Check(1) = MaximumAbsoluteValue(A - V * D * V.t());
+      DiagonalMatrix I(10); I = 1;
+      Check(2) = MaximumAbsoluteValue(V * V.t() - I);
+      Check(3) = MaximumAbsoluteValue(V.t() * V - I);
+
+      EigenValues(AS, D1); CheckIsSorted(D1, true);
+      D -= D1;
+      Clean(D,0.000000001); Print(D);
+
+      Jacobi(AS,D,V);
+      Check(4) = MaximumAbsoluteValue(A - V * D * V.t());
+      Check(5) = MaximumAbsoluteValue(V * V.t() - I);
+      Check(6) = MaximumAbsoluteValue(V.t() * V - I);
+
+      SortAscending(D);
+      D -= D1;
+      Clean(D,0.000000001); Print(D);
+
+      Clean(Check,0.000000001); Print(Check);
+
+      // Check loading rows
+
+      SymmetricMatrix B(10);
+
+      B.Row(1)  <<  1.00;
+      B.Row(2)  <<  0.07 <<  1.00;
+      B.Row(3)  <<  0.05 <<  0.05 <<  1.00;
+      B.Row(4)  <<  0.00 <<  0.05 <<  0.05 <<  1.00;
+      B.Row(5)  <<  0.06 << -0.03 <<  0.02 << -0.05 <<  1.00;
+      B.Row(6)  <<  0.09 <<  0.07 <<  0.01 <<  0.04 << -0.03
+                <<  1.00;
+      B.Row(7)  <<  0.03 <<  0.00 << -0.05 <<  0.01 <<  0.02
+                << -0.06 <<  1.00;
+      B.Row(8)  <<  0.02 <<  0.07 <<  0.04 <<  0.02 << -0.02
+                <<  0.08 <<  0.09 <<  1.00;
+      B.Row(9)  <<  0.02 <<  0.00 <<  0.05 << -0.05 <<  0.04
+                << -0.02 <<  0.12 <<  0.00 <<  1.00;
+      B.Row(10) << -0.03 <<  0.02 << -0.03 <<  0.00 <<  0.00
+                << -0.10 << -0.03 << -0.02 <<  0.02 <<  1.00;
+
+      B -= AS; Print(B);
+
+   }
+
+   {
+      Tracer et1("Stage 6");
+      // badly scaled matrix
+      Matrix A(9,9);
+
+      A.Row(1) << 1.13324e+012 << 3.68788e+011 << 3.35163e+009
+               << 3.50193e+011 << 1.25335e+011 << 1.02212e+009
+               << 3.16602e+009 << 1.02418e+009 << 9.42959e+006;
+      A.Row(2) << 3.68788e+011 << 1.67128e+011 << 1.27449e+009
+               << 1.25335e+011 << 6.05413e+010 << 4.34573e+008
+               << 1.02418e+009 << 4.69192e+008 << 3.61098e+006;
+      A.Row(3) << 3.35163e+009 << 1.27449e+009 << 1.25571e+007
+               << 1.02212e+009 << 4.34573e+008 << 3.69769e+006
+               << 9.42959e+006 << 3.61098e+006 << 3.59450e+004;
+      A.Row(4) << 3.50193e+011 << 1.25335e+011 << 1.02212e+009
+               << 1.43514e+011 << 5.42310e+010 << 4.15822e+008
+               << 1.23068e+009 << 4.31545e+008 << 3.58714e+006;
+      A.Row(5) << 1.25335e+011 << 6.05413e+010 << 4.34573e+008
+               << 5.42310e+010 << 2.76601e+010 << 1.89102e+008
+               << 4.31545e+008 << 2.09778e+008 << 1.51083e+006;
+      A.Row(6) << 1.02212e+009 << 4.34573e+008 << 3.69769e+006
+               << 4.15822e+008 << 1.89102e+008 << 1.47143e+006
+               << 3.58714e+006 << 1.51083e+006 << 1.30165e+004;
+      A.Row(7) << 3.16602e+009 << 1.02418e+009 << 9.42959e+006
+               << 1.23068e+009 << 4.31545e+008 << 3.58714e+006
+               << 1.12335e+007 << 3.54778e+006 << 3.34311e+004;
+      A.Row(8) << 1.02418e+009 << 4.69192e+008 << 3.61098e+006
+               << 4.31545e+008 << 2.09778e+008 << 1.51083e+006
+               << 3.54778e+006 << 1.62552e+006 << 1.25885e+004;
+      A.Row(9) << 9.42959e+006 << 3.61098e+006 << 3.59450e+004
+               << 3.58714e+006 << 1.51083e+006 << 1.30165e+004
+               << 3.34311e+004 << 1.25885e+004 << 1.28000e+002;
+
+
+      SymmetricMatrix AS; AS << A;
+      Matrix V; DiagonalMatrix D, D1;
+      ColumnVector Check(6);
+      EigenValues(AS,D,V); CheckIsSorted(D, true);
+      Check(1) = MaximumAbsoluteValue(A - V * D * V.t()) / 100000;
+      DiagonalMatrix I(9); I = 1;
+      Check(2) = MaximumAbsoluteValue(V * V.t() - I);
+      Check(3) = MaximumAbsoluteValue(V.t() * V - I);
+
+      EigenValues(AS, D1);
+      D -= D1;
+      Clean(D,0.001); Print(D);
+
+      Jacobi(AS,D,V);
+      Check(4) = MaximumAbsoluteValue(A - V * D * V.t()) / 100000;
+      Check(5) = MaximumAbsoluteValue(V * V.t() - I);
+      Check(6) = MaximumAbsoluteValue(V.t() * V - I);
+
+      SortAscending(D);
+      D -= D1;
+      Clean(D,0.001); Print(D);
+
+      Clean(Check,0.0000001); Print(Check);
+   }
+
+   {
+      Tracer et1("Stage 7");
+      // matrix with all singular values close to 1
+      Matrix A(8,8);
+      A.Row(1)<<-0.4343<<-0.0445<<-0.4582<<-0.1612<<-0.3191<<-0.6784<<0.1068<<0;
+      A.Row(2)<<0.5791<<0.5517<<0.2575<<-0.1055<<-0.0437<<-0.5282<<0.0442<<0;
+      A.Row(3)<<0.5709<<-0.5179<<-0.3275<<0.2598<<-0.196<<-0.1451<<-0.4143<<0;
+      A.Row(4)<<0.2785<<-0.5258<<0.1251<<-0.4382<<0.0514<<-0.0446<<0.6586<<0;
+      A.Row(5)<<0.2654<<0.3736<<-0.7436<<-0.0122<<0.0376<<0.3465<<0.3397<<0;
+      A.Row(6)<<0.0173<<-0.0056<<-0.1903<<-0.7027<<0.4863<<-0.0199<<-0.4825<<0;
+      A.Row(7)<<0.0434<<0.0966<<0.1083<<-0.4576<<-0.7857<<0.3425<<-0.1818<<0;
+      A.Row(8)<<0.0<<0.0<<0.0<<0.0<<0.0<<0.0<<0.0<<-1.0;
+      Matrix U,V; DiagonalMatrix D;
+      SVD(A,D,U,V); CheckIsSorted(D);
+      Matrix B = U * D * V.t() - A; Clean(B,0.000000001); Print(B);
+      DiagonalMatrix I(8); I = 1; D -= I; Clean(D,0.0001); Print(D);
+      U *= U.t(); U -= I; Clean(U,0.000000001); Print(U);
+      V *= V.t(); V -= I; Clean(V,0.000000001); Print(V);
+
+   }
+
+   {
+      Tracer et1("Stage 8");
+      // check SortSV functions
+
+      Matrix A(15, 10);
+      int i, j;
+      for (i = 1; i <= 15; ++i) for (j = 1; j <= 10; ++j)
+         A(i, j) = i + j / 1000.0;
+      DiagonalMatrix D(10);
+      D << 0.2 << 0.5 << 0.1 << 0.7 << 0.8 << 0.3 << 0.4 << 0.7 << 0.9 << 0.6;
+      Matrix U = A; Matrix V = 10 - 2 * A;
+      Matrix Prod = U * D * V.t();
+
+      DiagonalMatrix D2 = D; SortDescending(D2);
+      DiagonalMatrix D1 = D; SortSV(D1, U, V); Matrix X = D1 - D2; Print(X);
+      X = Prod - U * D1 * V.t(); Clean(X,0.000000001); Print(X);
+      U = A; V = 10 - 2 * A;
+      D1 = D; SortSV(D1, U); X = D1 - D2; Print(X);
+      D1 = D; SortSV(D1, V); X = D1 - D2; Print(X);
+      X = Prod - U * D1 * V.t(); Clean(X,0.000000001); Print(X);
+
+      D2 = D; SortAscending(D2);
+      U = A; V = 10 - 2 * A;
+      D1 = D; SortSV(D1, U, V, true); X = D1 - D2; Print(X);
+      X = Prod - U * D1 * V.t(); Clean(X,0.000000001); Print(X);
+      U = A; V = 10 - 2 * A;
+      D1 = D; SortSV(D1, U, true); X = D1 - D2; Print(X);
+      D1 = D; SortSV(D1, V, true); X = D1 - D2; Print(X);
+      X = Prod - U * D1 * V.t(); Clean(X,0.000000001); Print(X);
+   }
+
+   {
+      Tracer et1("Stage 9");
+      // Tom William's example
+      Matrix A(10,10);
+      Matrix U;
+      Matrix V;
+      DiagonalMatrix Sigma;
+      Real myVals[] =
+      {
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    0,
+         1,    1,    1,    1,    1,    1,    1,    1,    1,    0,
+         1,    1,    1,    1,    1,    1,    1,    1,    0,    0,
+         1,    1,    1,    1,    1,    1,    1,    0,    0,    0,
+         1,    1,    1,    1,    1,    0,    0,    0,    0,    0,
+      };
+
+      A << myVals;
+      SVD(A, Sigma, U, V); CheckIsSorted(Sigma);
+      A -= U * Sigma * V.t();
+      Clean(A, 0.000000001); Print(A);
+   }
+
+
+
+}
Index: Shared/newmat/extra/tmtf.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtf.cpp
diff -N Shared/newmat/extra/tmtf.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtf.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,422 @@
+
+//#define WANT_STREAM
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmatap.h"
+
+//#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+static void SlowFT(const ColumnVector& a, const ColumnVector&b,
+   ColumnVector& x, ColumnVector& y)
+{
+   int n = a.Nrows();
+   x.ReSize(n); y.ReSize(n);
+   Real f = 6.2831853071795864769/n;
+   for (int j=1; j<=n; j++)
+   {
+      Real sumx = 0.0; Real sumy = 0.0;
+      for (int k=1; k<=n; k++)
+      {
+	 Real theta = - (j-1) * (k-1) * f;
+	 Real c = cos(theta); Real s = sin(theta);
+	 sumx += c * a(k) - s * b(k); sumy += s * a(k) + c * b(k);
+      }
+      x(j) = sumx; y(j) = sumy;
+   }
+}
+
+static void SlowDTT_II(const ColumnVector& a, ColumnVector& c, ColumnVector& s)
+{
+   int n = a.Nrows(); c.ReSize(n); s.ReSize(n);
+   Real f = 6.2831853071795864769 / (4*n);
+   int k;
+
+   for (k=1; k<=n; k++)
+   {
+      Real sum = 0.0;
+      const int k1 = k-1;              // otherwise Visual C++ 5 fails
+      for (int j=1; j<=n; j++) sum += cos(k1 * (2*j-1) * f) * a(j);
+      c(k) = sum;
+   }
+
+   for (k=1; k<=n; k++)
+   {
+      Real sum = 0.0;
+      for (int j=1; j<=n; j++) sum += sin(k * (2*j-1) * f) * a(j);
+      s(k) = sum;
+   }
+}
+
+static void SlowDTT(const ColumnVector& a, ColumnVector& c, ColumnVector& s)
+{
+   int n1 = a.Nrows(); int n = n1 - 1;
+   c.ReSize(n1); s.ReSize(n1);
+   Real f = 6.2831853071795864769 / (2*n);
+   int k;
+
+   int sign = 1;
+   for (k=1; k<=n1; k++)
+   {
+      Real sum = 0.0;
+      for (int j=2; j<=n; j++) sum += cos((j-1) * (k-1) * f) * a(j);
+      c(k) = sum + (a(1) + sign * a(n1)) / 2.0;
+      sign = -sign;
+   }
+
+   for (k=2; k<=n; k++)
+   {
+      Real sum = 0.0;
+      for (int j=2; j<=n; j++) sum += sin((j-1) * (k-1) * f) * a(j);
+      s(k) = sum;
+   }
+   s(1) = s(n1) = 0;
+}
+
+void SlowFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y)
+{
+   Tracer trace("SlowFT2");
+   int m = U.Nrows(); int n = U.Ncols();
+   if (m != V.Nrows() || n != V.Ncols() || m == 0 || n == 0)
+      Throw(ProgramException("Matrix dimensions unequal or zero", U, V));
+   X.ReSize(U); Y.ReSize(V);
+   const Real pi2 = atan(1.0) * 8.0;
+   for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j)
+   {
+      Real sumr = 0.0, sumi = 0.0;
+      for (int k = 0; k < m; ++k) for (int l = 0; l < n; ++l)
+      {
+         Real a = -pi2 * ( (Real)k * (Real)i / (Real)m
+            + (Real)j * (Real)l / (Real)n );
+         Real cs = cos(a); Real sn = sin(a);
+         sumr += cs * U(k+1,l+1) - sn * V(k+1,l+1);
+         sumi += cs * V(k+1,l+1) + sn * U(k+1,l+1);
+      }
+      X(i+1,j+1) = sumr; Y(i+1,j+1) = sumi;
+   }
+}
+
+
+static void test(int n)
+{
+   Tracer et("Test FFT");
+   MultWithCarry mwc;
+
+   ColumnVector A(n), B(n), X, Y;
+   for (int i=0; i<n; i++)
+      { A.element(i) = mwc.Next(); B.element(i) = mwc.Next(); }
+   FFT(A, B, X, Y); FFTI(X, Y, X, Y);
+   X = X - A; Y = Y - B;
+   Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y);
+}
+
+static void test1(int n)
+{
+   Tracer et("Test RealFFT");
+   MultWithCarry mwc;
+
+   ColumnVector A(n), B(n), X, Y;
+   for (int i=0; i<n; i++) A.element(i) = mwc.Next();
+   B = 0.0;
+   FFT(A, B, X, Y);
+   B.CleanUp();                 // release some space
+   int n2 = n/2+1;
+   ColumnVector X1,Y1,X2,Y2;
+   RealFFT(A, X1, Y1);
+   X2 = X1 - X.Rows(1,n2); Y2 = Y1 - Y.Rows(1,n2);
+   Clean(X2,0.000000001); Clean(Y2,0.000000001); Print(X2); Print(Y2);
+   X2.CleanUp(); Y2.CleanUp();  // release some more space
+   RealFFTI(X1,Y1,B);
+   B = A - B;
+   Clean(B,0.000000001); Print(B);
+}
+
+static void test2(int n)
+{
+   Tracer et("cf FFT and slow FT");
+   MultWithCarry mwc;
+
+   ColumnVector A(n), B(n), X, Y, X1, Y1;
+   for (int i=0; i<n; i++)
+      { A.element(i) = mwc.Next(); B.element(i) = mwc.Next(); }
+   FFT(A, B, X, Y);
+   SlowFT(A, B, X1, Y1);
+   X = X - X1; Y = Y - Y1;
+   Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y);
+}
+
+static void test3(int n)
+{
+   Tracer et("cf slow and fast DCT_II and DST_II");
+   MultWithCarry mwc;
+
+   ColumnVector A(n), X, Y, X1, Y1;
+   for (int i=0; i<n; i++) A.element(i) = mwc.Next();
+   DCT_II(A, X); DST_II(A, Y);
+   SlowDTT_II(A, X1, Y1);
+   X -= X1; Y -= Y1;
+   Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y);
+}
+
+static void test4(int n)
+{
+   Tracer et("Test DCT_II");
+   MultWithCarry mwc;
+
+   ColumnVector A1(n);
+   for (int i=0; i<n; i++) A1.element(i) = mwc.Next();
+   // do DCT II by ordinary FFT
+   ColumnVector P(2*n), Q(2*n);
+   P = 0.0; Q = 0.0; P.Rows(1,n) = A1;
+   FFT(P, Q, P, Q);
+   ColumnVector B1(n);
+   for (int k=0; k<n; k++)
+   {
+      Real arg = k * 6.2831853071795864769 / (4 * n);
+      B1(k+1) = P(k+1) * cos(arg) + Q(k+1) * sin(arg);
+   }
+   // use DCT_II routine
+   ColumnVector B2;
+   DCT_II(A1,B2);
+   // test inverse
+   ColumnVector A2;
+   DCT_II_inverse(B2,A2);
+   A1 -= A2; B1 -= B2;
+   Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1);
+}
+
+static void test5(int n)
+{
+   Tracer et("Test DST_II");
+   MultWithCarry mwc;
+
+   ColumnVector A1(n);
+   for (int i=0; i<n; i++) A1.element(i) = mwc.Next();
+   // do DST II by ordinary FFT
+   ColumnVector P(2*n), Q(2*n);
+   P = 0.0; Q = 0.0; P.Rows(1,n) = A1;
+   FFT(P, Q, P, Q);
+   ColumnVector B1(n);
+   for (int k=1; k<=n; k++)
+   {
+      Real arg = k * 6.2831853071795864769 / (4 * n);
+      B1(k) = P(k+1) * sin(arg) - Q(k+1) * cos(arg);
+   }
+   // use DST_II routine
+   ColumnVector B2;
+   DST_II(A1,B2);
+   // test inverse
+   ColumnVector A2;
+   DST_II_inverse(B2,A2);
+   A1 -= A2; B1 -= B2;
+   Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1);
+}
+
+static void test6(int n)
+{
+   Tracer et("Test DST");
+   MultWithCarry mwc;
+
+   ColumnVector A1(n+1);
+   A1(1) = A1(n+1) = 0;
+   for (int i=1; i<n; i++) A1.element(i) = mwc.Next();
+
+   // do DST by ordinary FFT
+   ColumnVector P(2*n), Q(2*n); P = 0.0; Q = 0.0; P.Rows(1,n+1) = A1;
+   FFT(P, Q, P, Q);
+   ColumnVector B1 = -Q.Rows(1,n+1);
+   // use DST routine
+   ColumnVector B2;
+   DST(A1,B2);
+   // test inverse
+   ColumnVector A2;
+   DST_inverse(B2,A2);
+   A1 -= A2; B1 -= B2;
+   Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1);
+}
+
+
+
+static void test7(int n)
+{
+   Tracer et("Test DCT");
+   MultWithCarry mwc;
+
+   ColumnVector A1(n+1);
+   for (int i=0; i<=n; i++) A1.element(i) = mwc.Next();
+
+   // do DCT by ordinary FFT
+   ColumnVector P(2*n), Q(2*n); P = 0.0; Q = 0.0; P.Rows(1,n+1) = A1;
+   P(1) /= 2.0; P(n+1) /= 2.0;
+   FFT(P, Q, P, Q);
+   ColumnVector B1 = P.Rows(1,n+1);
+   // use DCT routine
+   ColumnVector B2;
+   DCT(A1,B2);
+   // test inverse
+   ColumnVector A2;
+   DCT_inverse(B2,A2);
+   A1 -= A2; B1 -= B2;
+   Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1);
+}
+
+static void test8(int n)
+{
+   Tracer et("cf slow and fast DCT and DST");
+   MultWithCarry mwc;
+
+   ColumnVector A(n+1), X, Y, X1, Y1;
+   for (int i=0; i<=n; i++) A.element(i) = mwc.Next();
+
+   DCT(A, X); DST(A, Y);
+   SlowDTT(A, X1, Y1);
+   X -= X1; Y -= Y1;
+   Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y);
+}
+
+static void test9(int m, int n)
+{
+   Tracer et("cf FFT2 and slow FT2");
+   MultWithCarry mwc;
+
+   Matrix A(m,n), B(m,n), X, Y, X1, Y1;
+   for (int i=0; i<m; i++) for (int j=0; j<n; j++)
+      { A.element(i,j) = mwc.Next(); B.element(i,j) = mwc.Next(); }
+   FFT2(A, B, X, Y);
+   SlowFT2(A, B, X1, Y1);
+   X = X - X1; Y = Y - Y1;
+   Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y);
+   FFT2I(X1, Y1, X1, Y1);
+   X1 -= A; Y1 -= B;
+   Clean(X1,0.000000001); Clean(Y1,0.000000001); Print(X1); Print(Y1);   
+}
+
+
+
+
+void trymatf()
+{
+   Tracer et("Fifteenth test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i;
+   ColumnVector A(12), B(12);
+   for (i = 1; i <=12; i++)
+   {
+      Real i1 = i - 1;
+      A(i) = .7
+	   + .2 * cos(6.2831853071795864769 * 4.0 * i1 / 12)
+	   + .3 * sin(6.2831853071795864769 * 3.0 * i1 / 12);
+      B(i) = .9
+	   + .5 * sin(6.2831853071795864769 * 2.0 * i1 / 12)
+	   + .4 * cos(6.2831853071795864769 * 1.0 * i1 / 12);
+   }
+   FFT(A, B, A, B);
+   A(1) -= 8.4; A(3) -= 3.0; A(5) -= 1.2; A(9) -= 1.2; A(11) += 3.0;
+   B(1) -= 10.8; B(2) -= 2.4; B(4) += 1.8; B(10) -= 1.8; B(12) -= 2.4;
+   Clean(A,0.000000001); Clean(B,0.000000001); Print(A); Print(B);
+
+
+   // test FFT
+   test(2048); test(2000); test(27*81); test(2310); test(49*49);
+   test(13*13*13); test(43*47);
+   test(16*16*3); test(16*16*5); test(16*16*7);
+   test(8*8*5);
+
+   // test realFFT
+   test1(2); test1(98); test1(22); test1(100);
+   test1(2048); test1(2000); test1(35*35*2);
+
+   // compare FFT and slowFFT
+   test2(1); test2(13); test2(12); test2(9); test2(16); test2(30); test2(42);
+   test2(24); test2(8); test2(40); test2(48); test2(4); test2(3); test2(5);
+   test2(32); test2(2);
+
+   // compare DCT_II, DST_II and slow versions
+   test3(2); test3(26); test3(32); test3(18);
+
+   // test DCT_II and DST_II
+   test4(2); test5(2);
+   test4(202); test5(202);
+   test4(1000); test5(1000);
+
+   // test DST and DCT
+   test6(2); test7(2);
+   test6(274); test7(274);
+   test6(1000); test7(1000);
+
+   // compare DCT, DST and slow versions
+   test8(2); test8(26); test8(32); test8(18);
+
+   // compare FFT2 with slow version
+   test9(1,16); test9(16,1);
+   test9(4,3); test9(4,4); test9(4,5); test9(5,3);
+
+   
+   // now do the same thing all over again forcing use of old FFT
+   FFT_Controller::OnlyOldFFT = true;
+
+   for (i = 1; i <=12; i++)
+   {
+      Real i1 = i - 1;
+      A(i) = .7
+	   + .2 * cos(6.2831853071795864769 * 4.0 * i1 / 12)
+	   + .3 * sin(6.2831853071795864769 * 3.0 * i1 / 12);
+      B(i) = .9
+	   + .5 * sin(6.2831853071795864769 * 2.0 * i1 / 12)
+	   + .4 * cos(6.2831853071795864769 * 1.0 * i1 / 12);
+   }
+   FFT(A, B, A, B);
+   A(1) -= 8.4; A(3) -= 3.0; A(5) -= 1.2; A(9) -= 1.2; A(11) += 3.0;
+   B(1) -= 10.8; B(2) -= 2.4; B(4) += 1.8; B(10) -= 1.8; B(12) -= 2.4;
+   Clean(A,0.000000001); Clean(B,0.000000001); Print(A); Print(B);
+
+
+   // test FFT
+   test(2048); test(2000); test(27*81); test(2310); test(49*49);
+   test(13*13*13); test(43*47);
+   test(16*16*3); test(16*16*5); test(16*16*7);
+   test(8*8*5);
+
+   // test realFFT
+   test1(2); test1(98); test1(22); test1(100);
+   test1(2048); test1(2000); test1(35*35*2);
+
+   // compare FFT and slowFFT
+   test2(1); test2(13); test2(12); test2(9); test2(16); test2(30); test2(42);
+   test2(24); test2(8); test2(40); test2(48); test2(4); test2(3); test2(5);
+   test2(32); test2(2);
+
+   // compare DCT_II, DST_II and slow versions
+   test3(2); test3(26); test3(32); test3(18);
+
+   // test DCT_II and DST_II
+   test4(2); test5(2);
+   test4(202); test5(202);
+   test4(1000); test5(1000);
+
+   // test DST and DCT
+   test6(2); test7(2);
+   test6(274); test7(274);
+   test6(1000); test7(1000);
+
+   // compare DCT, DST and slow versions
+   test8(2); test8(26); test8(32); test8(18);
+   
+   // compare FFT2 with slow version
+   // don't redo these
+
+   FFT_Controller::OnlyOldFFT = false;
+
+
+
+}
Index: Shared/newmat/extra/tmtg.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtg.cpp
diff -N Shared/newmat/extra/tmtg.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtg.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,154 @@
+
+//#define WANT_STREAM
+
+#define WANT_MATH                   // for sqrt
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+void trymatg()
+{
+//   cout << "\nSixteenth test of Matrix package\n";
+//   cout << "\n";
+   Tracer et("Sixteenth test of Matrix package");
+   Tracer::PrintTrace();
+
+   int i,j;
+   Matrix M(4,7);
+   for (i=1; i<=4; i++) for (j=1; j<=7; j++) M(i,j) = 100 * i + j;
+   ColumnVector CV = M.AsColumn();
+   {
+      Tracer et1("Stage 1");
+      RowVector test(7);
+      test(1) = SumSquare(M);
+      test(2) = SumSquare(CV);
+      test(3) = SumSquare(CV.t());
+      test(4) = SumSquare(CV.AsDiagonal());
+      test(5) = SumSquare(M.AsColumn());
+      test(6) = Matrix(CV.t()*CV)(1,1);
+      test(7) = (CV.t()*CV).AsScalar();
+      test = test - 2156560.0; Print(test);
+   }
+
+   UpperTriangularMatrix U(6);
+   for (i=1; i<=6; i++) for (j=i; j<=6; j++) U(i,j) = i + (i-j) * (i-j);
+   M = U; DiagonalMatrix D; D << U;
+   LowerTriangularMatrix L = U.t(); SymmetricMatrix S; S << (L+U)/2.0;
+   {
+      Tracer et1("Stage 2");
+      RowVector test(6);
+      test(1) = U.Trace();
+      test(2) = L.Trace();
+      test(3) = D.Trace();
+      test(4) = S.Trace();
+      test(5) = M.Trace();
+      test(6) = ((L+U)/2.0).Trace();
+      test = test - 21; Print(test);
+      test(1) = LogDeterminant(U).Value();
+      test(2) = LogDeterminant(L).Value();
+      test(3) = LogDeterminant(D).Value();
+      test(4) = LogDeterminant(D).Value();
+      test(5) = LogDeterminant((L+D)/2.0).Value();
+      test(6) = Determinant((L+D)/2.0);
+      test = test - 720; Clean(test,0.000000001); Print(test);
+   }
+
+   {
+      Tracer et1("Stage 3");
+      S << L*U; M = S;
+      RowVector test(8);
+      test(1) = LogDeterminant(S).Value();
+      test(2) = LogDeterminant(M).Value();
+      test(3) = LogDeterminant(L*U).Value();
+      test(4) = LogDeterminant(Matrix(L*L)).Value();
+      test(5) = Determinant(S);
+      test(6) = Determinant(M);
+      test(7) = Determinant(L*U);
+      test(8) = Determinant(Matrix(L*L));
+      test = test - 720.0 * 720.0; Clean(test,0.00000001); Print(test);
+   }
+
+   {
+      Tracer et1("Stage 4");
+      M = S * S;
+      Matrix SX = S;
+      RowVector test(3);
+      test(1) = SumSquare(S);
+      test(2) = SumSquare(SX);
+      test(3) = Trace(M);
+		test = test - 3925961.0; Print(test);
+   }
+   {
+      Tracer et1("Stage 5");
+      SymmetricMatrix SM(10), SN(10);
+      Real S = 0.0;
+      for (i=1; i<=10; i++) for (j=i; j<=10; j++)
+      {
+         SM(i,j) = 1.5 * i - j; SN(i,j) = SM(i,j) * SM(i,j);
+         if (SM(i,j) < 0.0)   SN(i,j) = - SN(i,j);
+         S += SN(i,j) * ((i==j) ? 1.0 : 2.0);
+      }
+      Matrix M = SM, N = SN; RowVector test(4);
+      test(1) = SumAbsoluteValue(SN);
+      test(2) = SumAbsoluteValue(-SN);
+      test(3) = SumAbsoluteValue(N);
+      test(4) = SumAbsoluteValue(-N);
+      test = test - 1168.75; Print(test);
+      test(1) = Sum(SN);
+      test(2) = -Sum(-SN);
+      test(3) = Sum(N);
+      test(4) = -Sum(-N);
+      test = test - S; Print(test);
+      test(1) = MaximumAbsoluteValue(SM);
+      test(2) = MaximumAbsoluteValue(-SM);
+      test(3) = MaximumAbsoluteValue(M);
+      test(4) = MaximumAbsoluteValue(-M);
+      test = test - 8.5; Print(test);
+   }
+   {
+      Tracer et1("Stage 6");
+      Matrix M(15,20); Real value = 0.0;
+      for (i=1; i<=15; i++) { for (j=1; j<=20; j++) M(i,j) = 1.5 * i - j; }
+      for (i=1; i<=20; i++)
+      { Real v = SumAbsoluteValue(M.Column(i)); if (value<v) value = v; }
+      RowVector test(3);
+      test(1) = value;
+      test(2) = Norm1(M);
+      test(3) = NormInfinity(M.t());
+      test = test - 165; Print(test);
+      test.ReSize(5);
+      ColumnVector CV = M.AsColumn(); M = CV.t();
+      test(1) = Norm1(CV.t());
+      test(2) = MaximumAbsoluteValue(M);
+      test(3) = NormInfinity(CV);
+      test(4) = Norm1(M);
+      test(5) = NormInfinity(M.t());
+      test = test - 21.5; Print(test);
+   }
+   {
+      Tracer et1("Stage 7");
+      Matrix M(15,20);
+      for (i=1; i<=15; i++) { for (j=1; j<=20; j++) M(i,j) = 2.5 * i - j; }
+      SymmetricMatrix SM; SM << M * M.t();
+      ColumnVector test(6);
+      test(1) = sqrt(SumSquare(M)) - NormFrobenius(M);
+      Real a = sqrt(SumSquare(SM));
+      test(2) = NormFrobenius(M * M.t()) - a;
+      test(3) = SM.NormFrobenius() - a;
+      test(4) = (M * M.t()).NormFrobenius() - a;
+      test(5) = NormFrobenius(SM) - a;
+      test(6) = Trace(SM) - M.SumSquare();
+      Clean(test, 0.00000001); Print(test);
+  }
+
+//   cout << "\nEnd of Sixteenth test\n";
+}
Index: Shared/newmat/extra/tmth.cpp
===================================================================
RCS file: Shared/newmat/extra/tmth.cpp
diff -N Shared/newmat/extra/tmth.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmth.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,766 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+//#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+static int my_max(int p, int q) { return (p > q) ? p : q; }
+
+static int my_min(int p, int q) { return (p < q) ? p : q; }
+
+
+void BandFunctions(int l1, int u1, int l2, int u2)
+{
+   int i, j;
+   BandMatrix BM1(20, l1, u1); BM1 = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l1 && i - j >= -u1) BM1(i, j) = 100 * i + j;
+
+   BandMatrix BM2 = BM1; Matrix M = BM2 - BM1; Print(M);
+
+   BM2.ReSize(20, l2, u2); BM2 = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l2 && i - j >= -u2) BM2(i, j) = (100 * i + j) * 11;
+
+   BandMatrix BMA = BM1 + BM2, BMS = BM1 - BM2, BMSP = SP(BM1, BM2),
+      BMM = BM1 * BM2, BMN = -BM1;
+
+   Matrix M1(20,20); M1 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l1 && i - j >= -u1) M1(i, j) = 100 * i + j;
+
+   Matrix M2(20,20); M2 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l2 && i - j >= -u2) M2(i, j) = (100 * i + j) * 11;
+
+   Matrix MA = M1 + M2, MS = M1 - M2, MSP = SP(M1, M2), MM = M1 * M2, MN = -M1;
+   MA -= BMA; MS -= BMS; MSP -= BMSP; MM -= BMM; MN -= BMN;
+   Print(MA); Print(MS); Print(MSP); Print(MM); Print(MN);
+
+   Matrix Test(7, 2);
+   Test(1,1) = BM1.BandWidth().Lower() - l1;
+   Test(1,2) = BM1.BandWidth().Upper() - u1;
+   Test(2,1) = BM2.BandWidth().Lower() - l2;
+   Test(2,2) = BM2.BandWidth().Upper() - u2;
+   Test(3,1) = BMA.BandWidth().Lower() - my_max(l1,l2);
+   Test(3,2) = BMA.BandWidth().Upper() - my_max(u1,u2);
+   Test(4,1) = BMS.BandWidth().Lower() - my_max(l1,l2);
+   Test(4,2) = BMS.BandWidth().Upper() - my_max(u1,u2);
+   Test(5,1) = BMSP.BandWidth().Lower() - my_min(l1,l2);
+   Test(5,2) = BMSP.BandWidth().Upper() - my_min(u1,u2);
+   Test(6,1) = BMM.BandWidth().Lower() - (l1 + l2);
+   Test(6,2) = BMM.BandWidth().Upper() - (u1 + u2);
+   Test(7,1) = BMN.BandWidth().Lower() - l1;
+   Test(7,2) = BMN.BandWidth().Upper() - u1;
+   Print(Test);
+
+   // test element function
+   BandMatrix BM1E(20, l1, u1); BM1E = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l1 && i - j >= -u1) BM1E.element(i-1, j-1) = 100 * i + j;
+   BandMatrix BM2E = BM1E; BM2E.ReSize(BM2); BM2E = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l2 && i - j >= -u2)
+         BM2E.element(i-1, j-1) = (100 * i + j) * 11;
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test element function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   const BandMatrix BM1C = BM1, BM2C = BM2;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l1 && i - j >= -u1)
+         BM1E.element(i-1, j-1) = BM1C.element(i-1, j-1);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l2 && i - j >= -u2)
+         BM2E.element(i-1, j-1) = BM2C.element(i-1, j-1);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test subscript function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l1 && i - j >= -u1) BM1E(i, j) = BM1C(i, j);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      if (i - j <= l2 && i - j >= -u2) BM2E(i, j) = BM2C(i, j);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+}
+
+void LowerBandFunctions(int l1, int l2)
+{
+   int i, j;
+   LowerBandMatrix BM1(20, l1); BM1 = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1(i, j) = 100 * i + j;
+
+   LowerBandMatrix BM2 = BM1; Matrix M = BM2 - BM1; Print(M);
+
+   BM2.ReSize(20, l2); BM2 = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2(i, j) = (100 * i + j) * 11;
+
+   LowerBandMatrix BMA = BM1 + BM2, BMS = BM1 - BM2, BMSP = SP(BM1, BM2),
+      BMM = BM1 * BM2, BMN = -BM1;
+
+   Matrix M1(20,20); M1 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) M1(i, j) = 100 * i + j;
+
+   Matrix M2(20,20); M2 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) M2(i, j) = (100 * i + j) * 11;
+
+   Matrix MA = M1 + M2, MS = M1 - M2, MSP = SP(M1, M2), MM = M1 * M2, MN = -M1;
+   MA -= BMA; MS -= BMS; MSP -= BMSP; MM -= BMM; MN -= BMN;
+   Print(MA); Print(MS); Print(MSP); Print(MM); Print(MN);
+
+   Matrix Test(7, 2);
+   Test(1,1) = BM1.BandWidth().Lower() - l1;
+   Test(1,2) = BM1.BandWidth().Upper();
+   Test(2,1) = BM2.BandWidth().Lower() - l2;
+   Test(2,2) = BM2.BandWidth().Upper();
+   Test(3,1) = BMA.BandWidth().Lower() - my_max(l1,l2);
+   Test(3,2) = BMA.BandWidth().Upper();
+   Test(4,1) = BMS.BandWidth().Lower() - my_max(l1,l2);
+   Test(4,2) = BMS.BandWidth().Upper();
+   Test(5,1) = BMSP.BandWidth().Lower() - my_min(l1,l2);
+   Test(5,2) = BMSP.BandWidth().Upper();
+   Test(6,1) = BMM.BandWidth().Lower() - (l1 + l2);
+   Test(6,2) = BMM.BandWidth().Upper();
+   Test(7,1) = BMN.BandWidth().Lower() - l1;
+   Test(7,2) = BMN.BandWidth().Upper();
+   Print(Test);
+
+   // test element function
+   LowerBandMatrix BM1E(20, l1); BM1E = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(i-1, j-1) = 100 * i + j;
+   LowerBandMatrix BM2E = BM1E; BM2E.ReSize(BM2); BM2E = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(i-1, j-1) = (100 * i + j) * 11;
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test element function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   const LowerBandMatrix BM1C = BM1, BM2C = BM2;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(i-1, j-1) = BM1C.element(i-1, j-1);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(i-1, j-1) = BM2C.element(i-1, j-1);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test subscript function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E(i, j) = BM1C(i, j);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E(i, j) = BM2C(i, j);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+}
+
+void UpperBandFunctions(int u1, int u2)
+{
+   int i, j;
+   UpperBandMatrix BM1(20, u1); BM1 = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u1) BM1(i, j) = 100 * i + j;
+
+   UpperBandMatrix BM2 = BM1; Matrix M = BM2 - BM1; Print(M);
+
+   BM2.ReSize(20, u2); BM2 = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u2) BM2(i, j) = (100 * i + j) * 11;
+
+   UpperBandMatrix BMA = BM1 + BM2, BMS = BM1 - BM2, BMSP = SP(BM1, BM2),
+      BMM = BM1 * BM2, BMN = -BM1;
+
+   Matrix M1(20,20); M1 = 0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u1) M1(i, j) = 100 * i + j;
+
+   Matrix M2(20,20); M2 = 0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u2) M2(i, j) = (100 * i + j) * 11;
+
+   Matrix MA = M1 + M2, MS = M1 - M2, MSP = SP(M1, M2), MM = M1 * M2, MN = -M1;
+   MA -= BMA; MS -= BMS; MSP -= BMSP; MM -= BMM; MN -= BMN;
+   Print(MA); Print(MS); Print(MSP); Print(MM); Print(MN);
+
+   Matrix Test(7, 2);
+   Test(1,1) = BM1.BandWidth().Lower();
+   Test(1,2) = BM1.BandWidth().Upper() - u1;
+   Test(2,1) = BM2.BandWidth().Lower();
+   Test(2,2) = BM2.BandWidth().Upper() - u2;
+   Test(3,1) = BMA.BandWidth().Lower();
+   Test(3,2) = BMA.BandWidth().Upper() - my_max(u1,u2);
+   Test(4,1) = BMS.BandWidth().Lower();
+   Test(4,2) = BMS.BandWidth().Upper() - my_max(u1,u2);
+   Test(5,1) = BMSP.BandWidth().Lower();
+   Test(5,2) = BMSP.BandWidth().Upper() - my_min(u1,u2);
+   Test(6,1) = BMM.BandWidth().Lower();
+   Test(6,2) = BMM.BandWidth().Upper() - (u1 + u2);
+   Test(7,1) = BMN.BandWidth().Lower();
+   Test(7,2) = BMN.BandWidth().Upper() - u1;
+   Print(Test);
+
+   // test element function
+   UpperBandMatrix BM1E(20, u1); BM1E = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u1) BM1E.element(i-1, j-1) = 100 * i + j;
+   UpperBandMatrix BM2E = BM1E; BM2E.ReSize(BM2); BM2E = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u2) BM2E.element(i-1, j-1) = (100 * i + j) * 11;
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test element function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   const UpperBandMatrix BM1C = BM1, BM2C = BM2;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u1) BM1E.element(i-1, j-1) = BM1C.element(i-1, j-1);
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u2) BM2E.element(i-1, j-1) = BM2C.element(i-1, j-1);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test subscript function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u1) BM1E(i, j) = BM1C(i, j);
+   for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      if (i - j >= -u2) BM2E(i, j) = BM2C(i, j);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+}
+
+void SymmetricBandFunctions(int l1, int l2)
+{
+   int i, j;
+   SymmetricBandMatrix BM1(20, l1); BM1 = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1(i, j) = 100 * i + j;
+
+   SymmetricBandMatrix BM2 = BM1; Matrix M = BM2 - BM1; Print(M);
+
+   BM2.ReSize(20, l2); BM2 = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2(i, j) = (100 * i + j) * 11;
+
+   SymmetricBandMatrix BMA = BM1 + BM2, BMS = BM1 - BM2, BMSP = SP(BM1, BM2),
+      BMN = -BM1;
+   BandMatrix BMM = BM1 * BM2;
+
+   SymmetricMatrix M1(20); M1 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) M1(i, j) = 100 * i + j;
+
+   SymmetricMatrix M2(20); M2 = 0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) M2(i, j) = (100 * i + j) * 11;
+
+   SymmetricMatrix MA = M1 + M2, MS = M1 - M2, MSP = SP(M1, M2), MN = -M1;
+   Matrix MM = M1 * M2;
+   MA -= BMA; MS -= BMS; MSP -= BMSP; MM -= BMM; MN -= BMN;
+   Print(MA); Print(MS); Print(MSP); Print(MM); Print(MN);
+
+   Matrix Test(7, 2);
+   Test(1,1) = BM1.BandWidth().Lower() - l1;
+   Test(1,2) = BM1.BandWidth().Upper() - l1;
+   Test(2,1) = BM2.BandWidth().Lower() - l2;
+   Test(2,2) = BM2.BandWidth().Upper() - l2;
+   Test(3,1) = BMA.BandWidth().Lower() - my_max(l1,l2);
+   Test(3,2) = BMA.BandWidth().Upper() - my_max(l1,l2);
+   Test(4,1) = BMS.BandWidth().Lower() - my_max(l1,l2);
+   Test(4,2) = BMS.BandWidth().Upper() - my_max(l1,l2);
+   Test(5,1) = BMSP.BandWidth().Lower() - my_min(l1,l2);
+   Test(5,2) = BMSP.BandWidth().Upper() - my_min(l1,l2);
+   Test(6,1) = BMM.BandWidth().Lower() - (l1 + l2);
+   Test(6,2) = BMM.BandWidth().Upper() - (l1 + l2);
+   Test(7,1) = BMN.BandWidth().Lower() - l1;
+   Test(7,2) = BMN.BandWidth().Upper() - l1;
+   Print(Test);
+
+   // test element function
+   SymmetricBandMatrix BM1E(20, l1); BM1E = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(i-1, j-1) = 100 * i + j;
+   SymmetricBandMatrix BM2E = BM1E; BM2E.ReSize(BM2); BM2E = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(i-1, j-1) = (100 * i + j) * 11;
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // reverse subscripts
+   BM1E = 999999.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(j-1, i-1) = 100 * i + j;
+   BM2E = 777777.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(j-1, i-1) = (100 * i + j) * 11;
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test element function with constant
+   BM1E = 444444.04; BM2E = 555555.0;
+   const SymmetricBandMatrix BM1C = BM1, BM2C = BM2;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(i-1, j-1) = BM1C.element(i-1, j-1);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(i-1, j-1) = BM2C.element(i-1, j-1);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // reverse subscripts
+   BM1E = 444444.0; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E.element(j-1, i-1) = BM1C.element(j-1, i-1);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E.element(j-1, i-1) = BM2C.element(j-1, i-1);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // test subscript function with constant
+   BM1E = 444444.0; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E(i, j) = BM1C(i, j);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E(i, j) = BM2C(i, j);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // reverse subscripts
+   BM1E = 444444.0; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E(j, i) = BM1C(j, i);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E(j, i) = BM2C(j, i);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+   // partly reverse subscripts
+   BM1E = 444444.0; BM2E = 555555.0;
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l1) BM1E(j, i) = BM1C(i, j);
+   for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      if (i - j <= l2) BM2E(j, i) = BM2C(i, j);
+   M1 = BM1E - BM1; Print(M1);
+   M2 = BM2E - BM2; Print(M2);
+
+}
+
+
+
+void trymath()
+{
+//   cout << "\nSeventeenth test of Matrix package\n";
+//   cout << "\n";
+   Tracer et("Seventeenth test of Matrix package");
+   Tracer::PrintTrace();
+
+
+   {
+      Tracer et1("Stage 1");
+      int i, j;
+      BandMatrix B(8,3,1);
+      for (i=1; i<=8; i++) for (j=-3; j<=1; j++)
+         { int k = i+j; if (k>0 && k<=8) B(i,k) = i + k/64.0; }
+
+      IdentityMatrix I(8); BandMatrix B1; B1 = I;
+      UpperTriangularMatrix UT = I; Print(Matrix(B1-UT));
+      Print(Matrix(B * B - B * 2 + I - (B - I) * (B - I)));
+      Matrix A = B; BandMatrix C; C = B;
+      Print(Matrix(B * A - C * 2 + I - (A - I) * (B - I)));
+
+      C.ReSize(8,2,2); C = 0.0; C.Inject(B);
+      Matrix X = A.t();
+      B1.ReSize(8,2,2); B1.Inject(X); Print(Matrix(C.t()-B1));
+
+      Matrix BI = B.i(); A = A.i()-BI; Clean(A,0.000000001); Print(A);
+      BandLUMatrix BLU = B.t();
+      BI = BLU.i(); A = X.i()-BI; Clean(A,0.000000001); Print(A);
+      X.ReSize(1,1);
+      X(1,1) = BLU.LogDeterminant().Value()-B.LogDeterminant().Value();
+      Clean(X,0.000000001); Print(X);
+
+      UpperBandMatrix U; U << B; LowerBandMatrix L; L << B;
+      DiagonalMatrix D; D << B;
+      Print( Matrix(L + (U - D - B)) );
+
+
+
+      for (i=1; i<=8; i++)  A.Column(i) << B.Column(i);
+      Print(Matrix(A-B));
+   }
+   {
+      Tracer et1("Stage 2");
+      BandMatrix A(7,2,2);
+      int i,j;
+      for (i=1; i<=7; i++) for (j=1; j<=7; j++)
+      {
+         int k=i-j; if (k<0) k = -k;
+         if (k==0) A(i,j)=6;
+         else if (k==1) A(i,j) = -4;
+         else if (k==2) A(i,j) = 1;
+         A(1,1) = A(7,7) = 5;
+      }
+      DiagonalMatrix D(7); D = 0.0; A = A - D;
+      BandLUMatrix B(A); Matrix M = A;
+      ColumnVector V(6);
+      V(1) = LogDeterminant(B).Value();
+      V(2) = LogDeterminant(A).Value();
+      V(3) = LogDeterminant(M).Value();
+      V(4) = Determinant(B);
+      V(5) = Determinant(A);
+      V(6) = Determinant(M);
+      V = V / 64 - 1; Clean(V,0.000000001); Print(V);
+      ColumnVector X(7);
+
+      Real a[] = {1,2,3,4,5,6,7};
+      X << a;
+      M = (M.i()*X).t() - (B.i()*X).t() * 2.0 + (A.i()*X).t();
+      Clean(M,0.000000001); Print(M);
+
+
+      BandMatrix P(80,2,5); ColumnVector CX(80);
+      for (i=1; i<=80; i++) for (j=1; j<=80; j++)
+      { int d = i-j; if (d<=2 && d>=-5) P(i,j) = i + j/100.0; }
+      for (i=1; i<=80; i++)  CX(i) = i*100.0;
+      Matrix MP = P;
+      ColumnVector V1 = P.i() * CX; ColumnVector V2 = MP.i() * CX;
+      V = V1 - V2; Clean(V,0.000000001); Print(V);
+
+      V1 = P * V1; V2 = MP * V2; V = V1 - V2; Clean(V,0.000000001); Print(V);
+      RowVector XX(1);
+      XX = LogDeterminant(P).Value() / LogDeterminant(MP).Value() - 1.0;
+      Clean(XX,0.000000001); Print(XX);
+
+      LowerBandMatrix LP(80,5);
+      for (i=1; i<=80; i++) for (j=1; j<=80; j++)
+      { int d = i-j; if (d<=5 && d>=0) LP(i,j) = i + j/100.0; }
+      MP = LP;
+      XX.ReSize(4);
+      XX(1) = LogDeterminant(LP).Value();
+      XX(2) = LogDeterminant(MP).Value();
+      V1 = LP.i() * CX; V2 = MP.i() * CX;
+      V = V1 - V2; Clean(V,0.000000001); Print(V);
+
+      UpperBandMatrix UP(80,4);
+      for (i=1; i<=80; i++) for (j=1; j<=80; j++)
+      { int d = i-j; if (d<=0 && d>=-4) UP(i,j) = i + j/100.0; }
+      MP = UP;
+      XX(3) = LogDeterminant(UP).Value();
+      XX(4) = LogDeterminant(MP).Value();
+      V1 = UP.i() * CX; V2 = MP.i() * CX;
+      V = V1 - V2; Clean(V,0.000000001); Print(V);
+      XX = XX / SumAbsoluteValue(XX) - .25; Clean(XX,0.000000001); Print(XX);
+   }
+
+   {
+      Tracer et1("Stage 3");
+      SymmetricBandMatrix SA(8,5);
+      int i,j;
+      for (i=1; i<=8; i++) for (j=1; j<=8; j++)
+         if (i-j<=5 && 0<=i-j) SA(i,j) =i + j/128.0;
+      DiagonalMatrix D(8); D = 10; SA = SA + D;
+
+      Matrix MA1(8,8); Matrix MA2(8,8);
+      for (i=1; i<=8; i++)
+         { MA1.Column(i) << SA.Column(i); MA2.Row(i) << SA.Row(i); }
+      Print(Matrix(MA1-MA2));
+
+      D = 10; SA = SA.t() + D; MA1 = MA1 + D;
+      Print(Matrix(MA1-SA));
+
+      UpperBandMatrix UB(8,3); LowerBandMatrix LB(8,4);
+      D << SA; UB << SA; LB << SA;
+      SA = SA * 5.0; D = D * 5.0; LB = LB * 5.0; UB = UB * 5.0;
+      BandMatrix B = LB - D + UB - SA; Print(Matrix(B));
+
+      SymmetricBandMatrix A(7,2); A = 100.0;
+      for (i=1; i<=7; i++) for (j=1; j<=7; j++)
+      {
+         int k=i-j;
+         if (k==0) A(i,j)=6;
+         else if (k==1) A(i,j) = -4;
+         else if (k==2) A(i,j) = 1;
+         A(1,1) = A(7,7) = 5;
+      }
+      BandLUMatrix C(A); Matrix M = A;
+      ColumnVector X(8);
+      X(1) = LogDeterminant(C).Value() - 64;
+      X(2) = LogDeterminant(A).Value() - 64;
+      X(3) = LogDeterminant(M).Value() - 64;
+      X(4) = SumSquare(M) - SumSquare(A);
+      X(5) = SumAbsoluteValue(M) - SumAbsoluteValue(A);
+      X(6) = MaximumAbsoluteValue(M) - MaximumAbsoluteValue(A);
+      X(7) = Trace(M) - Trace(A);
+      X(8) = Sum(M) - Sum(A);
+      Clean(X,0.000000001); Print(X);
+
+      Real a[] = {1,2,3,4,5,6,7};
+      X.ReSize(7);
+      X << a;
+      X = M.i()*X - C.i()*X * 2 + A.i()*X;
+      Clean(X,0.000000001); Print(X);
+
+
+      LB << A; UB << A; D << A;
+      BandMatrix XA = LB + (UB - D);
+      Print(Matrix(XA - A));
+
+      for (i=1; i<=7; i++) for (j=1; j<=7; j++)
+      {
+         int k=i-j;
+         if (k==0) A(i,j)=6;
+         else if (k==1) A(i,j) = -4;
+         else if (k==2) A(i,j) = 1;
+         A(1,1) = A(7,7) = 5;
+      }
+      D = 1;
+
+      M = LB.i() * LB - D; Clean(M,0.000000001); Print(M);
+      M = UB.i() * UB - D; Clean(M,0.000000001); Print(M);
+      M = XA.i() * XA - D; Clean(M,0.000000001); Print(M);
+      Matrix MUB = UB; Matrix MLB = LB;
+      M = LB.i() * UB - LB.i() * MUB; Clean(M,0.000000001); Print(M);
+      M = UB.i() * LB - UB.i() * MLB; Clean(M,0.000000001); Print(M);
+      M = LB.i() * UB - LB.i() * Matrix(UB); Clean(M,0.000000001); Print(M);
+      M = UB.i() * LB - UB.i() * Matrix(LB); Clean(M,0.000000001); Print(M);
+   }
+
+   {
+      // some tests about adding and subtracting band matrices of different
+      // sizes - check bandwidth of results
+      Tracer et1("Stage 4");
+
+      BandFunctions(9, 3, 9, 3);   // equal
+      BandFunctions(4, 7, 4, 7);   // equal
+      BandFunctions(9, 3, 5, 8);   // neither < or >
+      BandFunctions(5, 8, 9, 3);   // neither < or >
+      BandFunctions(9, 8, 5, 3);   // >
+      BandFunctions(3, 5, 8, 9);   // <
+
+      LowerBandFunctions(9, 9);    // equal
+      LowerBandFunctions(4, 4);    // equal
+      LowerBandFunctions(9, 5);    // >
+      LowerBandFunctions(3, 8);    // <
+
+      UpperBandFunctions(3, 3);    // equal
+      UpperBandFunctions(7, 7);    // equal
+      UpperBandFunctions(8, 3);    // >
+      UpperBandFunctions(5, 9);    // <
+
+      SymmetricBandFunctions(9, 9);   // equal
+      SymmetricBandFunctions(4, 4);   // equal
+      SymmetricBandFunctions(9, 5);   // >
+      SymmetricBandFunctions(3, 8);   // <
+
+      DiagonalMatrix D(6); D << 2 << 3 << 4.5 << 1.25 << 9.5 << -5;
+      BandMatrix BD = D;
+      UpperBandMatrix UBD; UBD = D;
+      LowerBandMatrix LBD; LBD = D;
+      SymmetricBandMatrix SBD = D;
+      Matrix X = BD - D; Print(X); X = UBD - D; Print(X);
+      X = LBD - D; Print(X); X = SBD - D; Print(X);
+      Matrix Test(9,2);
+      Test(1,1) =  BD.BandWidth().Lower(); Test(1,2) =  BD.BandWidth().Upper();
+      Test(2,1) = UBD.BandWidth().Lower(); Test(2,2) = UBD.BandWidth().Upper();
+      Test(3,1) = LBD.BandWidth().Lower(); Test(3,2) = LBD.BandWidth().Upper();
+      Test(4,1) = SBD.BandWidth().Lower(); Test(4,2) = SBD.BandWidth().Upper();
+
+      IdentityMatrix I(10); I *= 5;
+      BD = I; UBD = I; LBD = I; SBD = I;
+      X = BD - I; Print(X); X = UBD - I; Print(X);
+      X = LBD - I; Print(X); X = SBD - I; Print(X);
+      Test(5,1) =  BD.BandWidth().Lower(); Test(5,2) =  BD.BandWidth().Upper();
+      Test(6,1) = UBD.BandWidth().Lower(); Test(6,2) = UBD.BandWidth().Upper();
+      Test(7,1) = LBD.BandWidth().Lower(); Test(7,2) = LBD.BandWidth().Upper();
+      Test(8,1) = SBD.BandWidth().Lower(); Test(8,2) = SBD.BandWidth().Upper();
+
+      RowVector RV = D.AsRow(); I.ReSize(6); BandMatrix BI = I; I = 1;
+      BD =  RV.AsDiagonal() +  BI; X =  BD - D - I; Print(X);
+      Test(9,1) =  BD.BandWidth().Lower(); Test(9,2) =  BD.BandWidth().Upper();
+
+      Print(Test);
+   }
+
+   {
+      // various element functions
+      Tracer et1("Stage 5");
+
+      int i, j;
+      Matrix Count(1, 1); Count = 0;  // for counting errors
+      Matrix M(20,30);
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= 30; ++j)
+         M(i, j) = 100 * i + j;
+      const Matrix CM = M;
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= 30; ++j)
+      {
+         if (M(i, j) != CM(i, j)) ++Count(1,1);
+         if (M(i, j) != CM.element(i-1, j-1)) ++Count(1,1);
+         if (M(i, j) != M.element(i-1, j-1)) ++Count(1,1);
+      }
+
+      UpperTriangularMatrix U(20);
+      for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+         U(i, j) = 100 * i + j;
+      const UpperTriangularMatrix CU = U;
+      for (i = 1; i <= 20; ++i) for (j = i; j <= 20; ++j)
+      {
+         if (U(i, j) != CU(i, j)) ++Count(1,1);
+         if (U(i, j) != CU.element(i-1, j-1)) ++Count(1,1);
+         if (U(i, j) != U.element(i-1, j-1)) ++Count(1,1);
+      }
+
+      LowerTriangularMatrix L(20);
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+         L(i, j) = 100 * i + j;
+      const LowerTriangularMatrix CL = L;
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+      {
+         if (L(i, j) != CL(i, j)) ++Count(1,1);
+         if (L(i, j) != CL.element(i-1, j-1)) ++Count(1,1);
+         if (L(i, j) != L.element(i-1, j-1)) ++Count(1,1);
+      }
+
+      SymmetricMatrix S(20);
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= i; ++j)
+         S(i, j) = 100 * i + j;
+      const SymmetricMatrix CS = S;
+      for (i = 1; i <= 20; ++i) for (j = 1; j <= 20; ++j)
+      {
+         if (S(i, j) != CS(i, j)) ++Count(1,1);
+         if (S(i, j) != CS.element(i-1, j-1)) ++Count(1,1);
+         if (S(i, j) != S.element(i-1, j-1)) ++Count(1,1);
+         if (S(i, j) != S(j, i)) ++Count(1,1);
+         if (S(i, j) != CS(i, j)) ++Count(1,1);
+         if (S(i, j) != CS.element(i-1, j-1)) ++Count(1,1);
+         if (S(i, j) != S.element(i-1, j-1)) ++Count(1,1);
+      }
+
+      DiagonalMatrix D(20);
+      for (i = 1; i <= 20; ++i) D(i) = 100 * i + i * i;
+      const DiagonalMatrix CD = D;
+      for (i = 1; i <= 20; ++i)
+      {
+         if (D(i, i) != CD(i, i)) ++Count(1,1);
+         if (D(i, i) != CD.element(i-1, i-1)) ++Count(1,1);
+         if (D(i, i) != D.element(i-1, i-1)) ++Count(1,1);
+         if (D(i, i) != D(i)) ++Count(1,1);
+         if (D(i) != CD(i)) ++Count(1,1);
+         if (D(i) != CD.element(i-1)) ++Count(1,1);
+         if (D(i) != D.element(i-1)) ++Count(1,1);
+      }
+
+      RowVector R(20);
+      for (i = 1; i <= 20; ++i) R(i) = 100 * i + i * i;
+      const RowVector CR = R;
+      for (i = 1; i <= 20; ++i)
+      {
+         if (R(i) != CR(i)) ++Count(1,1);
+         if (R(i) != CR.element(i-1)) ++Count(1,1);
+         if (R(i) != R.element(i-1)) ++Count(1,1);
+      }
+
+      ColumnVector C(20);
+      for (i = 1; i <= 20; ++i) C(i) = 100 * i + i * i;
+      const ColumnVector CC = C;
+      for (i = 1; i <= 20; ++i)
+      {
+         if (C(i) != CC(i)) ++Count(1,1);
+         if (C(i) != CC.element(i-1)) ++Count(1,1);
+         if (C(i) != C.element(i-1)) ++Count(1,1);
+      }
+
+      Print(Count);
+
+   }
+
+   {
+      // resize to another matrix size
+      Tracer et1("Stage 6");
+
+      Matrix A(20, 30); A = 3;
+      Matrix B(3, 4);
+      B.ReSize(A); B = 6; B -= 2 * A; Print(B);
+
+      A.ReSize(25,25); A = 12;
+
+      UpperTriangularMatrix U(5);
+      U.ReSize(A); U = 12; U << (U - A); Print(U);
+
+      LowerTriangularMatrix L(5);
+      L.ReSize(U); L = 12; L << (L - A); Print(L);
+
+      DiagonalMatrix D(5);
+      D.ReSize(U); D = 12; D << (D - A); Print(D);
+
+      SymmetricMatrix S(5);
+      S.ReSize(U); S = 12; S << (S - A); Print(S);
+
+      IdentityMatrix I(5);
+      I.ReSize(U); I = 12; D << (I - A); Print(D);
+
+      A.ReSize(10, 1); A = 17;
+      ColumnVector C(5); C.ReSize(A); C = 17; C -= A; Print(C);
+
+      A.ReSize(1, 10); A = 15;
+      RowVector R(5); R.ReSize(A); R = 15; R -= A; Print(R);
+
+   }
+
+   {
+      // generic matrix and identity matrix
+      Tracer et1("Stage 7");
+      IdentityMatrix I(5);
+      I *= 4;
+      GenericMatrix GM = I;
+      GM /= 2;
+      DiagonalMatrix D = GM;
+      Matrix A = GM + 10;
+      A -= 10;
+      A -= D;
+      Print(A);
+   }
+
+   {
+      // SP and upper and lower triangular matrices
+      Tracer et1("Stage 8");
+      UpperTriangularMatrix UT(4);
+      UT << 3 << 7 << 3 << 9
+              << 5 << 2 << 6
+                   << 8 << 0
+                        << 4;
+      LowerTriangularMatrix LT; LT.ReSize(UT);
+      LT << 2
+         << 7 << 9
+         << 2 << 8 << 6
+         << 1 << 0 << 3 << 5;
+
+      DiagonalMatrix D = SP(UT, LT);
+      DiagonalMatrix D1(4);
+      D1 << 6 << 45 << 48 << 20;
+      D -= D1; Print(D);
+      BandMatrix BM = SP(UT, LT);
+      Matrix X = BM - D1; Print(X);
+      RowVector RV(2);
+      RV(1) = BM.BandWidth().Lower();
+      RV(2) = BM.BandWidth().Upper();
+      Print(RV);
+   }
+
+//   cout << "\nEnd of Seventeenth test\n";
+}
+
Index: Shared/newmat/extra/tmti.cpp
===================================================================
RCS file: Shared/newmat/extra/tmti.cpp
diff -N Shared/newmat/extra/tmti.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmti.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,209 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+//#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+void WillNotConverge()
+{
+   Matrix A(10,10);
+   Throw(ConvergenceException(A));
+}
+
+void ReSizeMatrix(Matrix& A)
+// for seeing if we can redimension a vector as a matrix
+{ A.ReSize(4,5); }
+
+void trymati()
+{
+#ifndef DisableExceptions
+   Tracer et("Eighteenth test of Matrix package");
+   Matrix RUStillThere(10,20); RUStillThere = 1553;
+   Tracer::PrintTrace();
+
+   ColumnVector checks(23); checks = 1.0; checks(1) = 0.0;
+
+   Try { WillNotConverge(); }
+   Catch(ConvergenceException) { checks(2) = 0; }
+   CatchAll { checks(1) = 1; }
+
+
+   Try { Matrix M(10,10); SymmetricMatrix S = M; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(3) = 0; }
+   CatchAll { checks(1) = 1; }
+
+
+   Try { Matrix M(10,10); M(10,11) = 2.0; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(IndexException) { checks(4) = 0; }
+   CatchAll { checks(1) = 1; }
+
+   Try { Matrix M(10,10); M = 0.0; M = M.i(); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(1) = 1; }
+   Catch(SingularException) { checks(5) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try { ColumnVector A(30), B(50);  A = 5; B = 3; FFT(A,B,A,B); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(6) = 0; }
+   CatchAll { checks(1) = 1; }
+
+   Try
+   {
+      ColumnVector A(30); A = 5; Matrix At = A.t();
+      DiagonalMatrix D;
+      SVD(At,D);
+   }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(Logic_error) { checks(6) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try { BandMatrix X(10,3,4); X(1,10) = 4.0; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(IndexException) { checks(7) = 0; }
+   CatchAll { checks(1) = 1; }
+
+   Try
+   {
+      SymmetricMatrix S(10); S = 5;
+      LowerTriangularMatrix L = Cholesky(S);
+   }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(1) = 1; }
+   Catch(NPDException) { checks(8) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try { BandMatrix M(10,3,5); M = 0.0; Matrix XM = M.i(); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(1) = 1; }
+   Catch(SingularException) { checks(9) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try { ColumnVector X(10); ColumnVector Y; X = 5; X = X - Y; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(IncompatibleDimensionsException) { checks(10) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try
+   {
+      UpperTriangularMatrix U(3); RowVector RV(3); RV = 10;
+      U.Row(2) = RV;
+   }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(11) = 0; }
+   Catch(Bad_alloc) { checks(1) = 1; }
+   CatchAndThrow;
+
+   Try { DiagonalMatrix D(3); D << 12 << 13 << 14 << 15; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(12) = 0; }
+   CatchAndThrow;
+
+   Try { ColumnVector D(3); D << 12 << 13; D << 1 << 2 << 3; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(13) = 0; }
+   CatchAndThrow;
+
+
+   Try {  { ColumnVector D(3); D << 12 << 13; }  }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(14) = 0; }
+   CatchAndThrow;
+
+   Try { ColumnVector CV; ReSizeMatrix(CV); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(VectorException) { checks(15) = 0; }
+   CatchAndThrow;
+
+   Try { RowVector RV(20); ReSizeMatrix(RV); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(VectorException) { checks(16) = 0; }
+   CatchAndThrow;
+
+   Try
+   {
+      UpperTriangularMatrix U(10); U = 5;
+      DiagonalMatrix D(10); D = 2;
+      D += U;                 // illegal conversion
+   }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(17) = 0; }
+   CatchAndThrow;
+
+   Try { Matrix A(2,3), B(2,3); if (A < B) A = B; }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(NotDefinedException) { checks(18) = 0; }
+   CatchAndThrow;
+
+   Try { SymmetricBandMatrix A(3,1); A = 1; A = A.Reverse(); }
+   Catch(ConvergenceException) { checks(1) = 1; }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(NotDefinedException) { checks(19) = 0; }
+   CatchAndThrow;
+
+   Try
+   {
+      Matrix A(5,5); A = 1.0;
+      UpperTriangularMatrix B(10);
+      B.SubMatrix(3,7,3,7) = A;
+   }
+   Catch(ProgramException) { checks(20) = 0; }
+   CatchAndThrow;
+
+   Try {  { RowVector D(1); D << 12 << 13; }  }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(21) = 0; }
+   CatchAndThrow;
+
+   Try {  { RowVector D(0); D << 12; }  }
+   Catch(InternalException) { checks(1) = 1; }
+   Catch(ProgramException) { checks(22) = 0; }
+   CatchAndThrow;
+
+   Try { Matrix M(10,10); Matrix XM(3,3); M = 0.0; XM = M.i(); }
+   Catch(SingularException) { checks(23) = 0; }
+   CatchAll { checks(1) = 1; }
+
+   Print(checks);
+   Matrix RUStillThere1(10,20); RUStillThere1 = 1553;
+   RUStillThere = RUStillThere - RUStillThere1;
+   Print(RUStillThere);
+#endif
+
+}
+
+
+
Index: Shared/newmat/extra/tmtj.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtj.cpp
diff -N Shared/newmat/extra/tmtj.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtj.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,152 @@
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+//#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+void trymatj()
+{
+   Tracer et("Nineteenth test of Matrix package");
+   Tracer::PrintTrace();
+   // testing elementwise (SP) products
+
+   {
+      Tracer et1("Stage 1");
+      Matrix A(13,7), B(13,7), C(13,7);
+      int i,j;
+      for (i=1;i<=13;i++) for (j=1; j<=7; j++)
+      {
+          Real a = (i+j*j)/2, b = (i*j-i/4);
+          A(i,j)=a; B(i,j)=b; C(i,j)=a*b;
+      }
+      // Where complete matrix routine can be used
+      Matrix X = SP(A,B)-C; Print(X);
+      X = SP(A,B+1.0)-A-C; Print(X);
+      X = SP(A-1,B)+B-C; Print(X);
+      X = SP(A-1,B+1)+B-A-C+1; Print(X);
+      // Where row-wise routine will be used
+      A = A.Rows(7,13); B = B.Rows(7,13); C = C.Rows(7,13);
+      LowerTriangularMatrix LTA; LTA << A;
+      UpperTriangularMatrix UTB; UTB << B;
+      DiagonalMatrix DC; DC << C;
+      X = SP(LTA,UTB) - DC; Print(X);
+      X = SP(LTA*2,UTB) - DC*2; Print(X);
+      X = SP(LTA, UTB /2) - DC/2; Print(X);
+      X = SP(LTA/2, UTB*2) - DC; Print(X);
+      DiagonalMatrix DX;
+      DX << SP(A,B); DX << (DX-C); Print(DX);
+      DX << SP(A*4,B); DX << (DX-C*4); Print(DX);
+      DX << SP(A,B*2); DX << (DX-C*2); Print(DX);
+      DX << SP(A/4,B/4); DX << (DX-C/16); Print(DX);
+      LowerTriangularMatrix LX;
+      LX = SP(LTA,B); LX << (LX-C); Print(LX);
+      LX = SP(LTA*3,B); LX << (LX-C*3); Print(LX);
+      LX = SP(LTA,B*5); LX << (LX-C*5); Print(LX);
+      LX = SP(-LTA,-B); LX << (LX-C); Print(LX);
+   }
+   {
+      // Symmetric Matrices
+      Tracer et1("Stage 2");
+      SymmetricMatrix A(25), B(25), C(25);
+      int i,j;
+      for (i=1;i<=25;i++) for (j=i;j<=25;j++)
+      {
+         Real a = i*j +i - j + 3;
+         Real b = i * i + j;
+         A(i,j)=a; B(i,j)=b; C(i,j)=a*b;
+      }
+      UpperTriangularMatrix UT;
+      UT << SP(A,B); UT << (UT - C); Print(UT);
+      Matrix MA = A, X;
+      X = SP(MA,B)-C; Print(X);
+      X = SP(A,B)-C; Print(X);
+      SymmetricBandMatrix BA(25,5), BB(25,5), BC(25,5);
+      BA.Inject(A); BB.Inject(B); BC.Inject(C);
+      X = SP(BA,BB)-BC; Print(X);
+      X = SP(BA*7,BB)-BC*7; Print(X);
+      X = SP(BA,BB/8)-BC/8; Print(X);
+      X = SP(BA*16,BB/16)-BC; Print(X);
+      X = SP(BA,BB); X=X-BC; Print(X);
+      X = SP(BA*2, BB/2)-BC; Print(X);
+      X = SP(BA, BB/2)-BC/2; Print(X);
+      X = SP(BA*2, BB)-BC*2; Print(X);
+   }
+   {
+      // Band matrices
+      Tracer et1("Stage 3");
+      Matrix A(19,19), B(19,19), C(19,19);
+      int i,j;
+      for (i=1;i<=19;i++) for (j=1;j<=19;j++)
+      {
+         Real a = i*j +i - 1.5*j + 3;
+         Real b = i * i + j;
+         A(i,j)=a; B(i,j)=b; C(i,j)=a*b;
+      }
+      BandMatrix BA(19,10,7), BB(19,8,15), BC(19,8,7);
+      BA.Inject(A); BB.Inject(B); BC.Inject(C);
+      Matrix X; BandMatrix BX; ColumnVector BW(2);
+      X = SP(BA,BB); X=X-BC; Print(X);
+      X = SP(BA/8,BB); X=X-BC/8; Print(X);
+      X = SP(BA,BB*17); X=X-BC*17; Print(X);
+      X = SP(BA/4,BB*7); X=X-BC*7/4; Print(X);
+      X = SP(BA,BB)-BC; Print(X);
+      X = SP(BA/8,BB)-BC/8; Print(X);
+      X = SP(BA,BB*17)-BC*17; Print(X);
+      X = SP(BA/4,BB*7)-BC*7/4; Print(X);
+      BX = SP(BA,BB);
+      BW(1)=BX.upper-7; BW(2)=BX.lower-8; Print(BW);
+
+      BA.ReSize(19,7,10); BB.ReSize(19,15,8);
+      BC.ReSize(19,7,8);
+      BA.Inject(A); BB.Inject(B); BC.Inject(C);
+
+      X = SP(BA,BB); X=X-BC; Print(X);
+      X = SP(BA/8,BB); X=X-BC/8; Print(X);
+      X = SP(BA,BB*17); X=X-BC*17; Print(X);
+      X = SP(BA/4,BB*7); X=X-BC*7/4; Print(X);
+      X = SP(BA,BB)-BC; Print(X);
+      X = SP(BA/8,BB)-BC/8; Print(X);
+      X = SP(BA,BB*17)-BC*17; Print(X);
+      X = SP(BA/4,BB*7)-BC*7/4; Print(X);
+      BX = SP(BA,BB);
+      BW(1)=BX.upper-8; BW(2)=BX.lower-7; Print(BW);
+   }
+   {
+      // SymmetricBandMatrices
+      Tracer et1("Stage 4");
+      Matrix A(7,7), B(7,7);
+      int i,j;
+      for (i=1;i<=7;i++) for (j=1;j<=7;j++)
+      {
+         Real a = i*j +i - 1.5*j + 3;
+         Real b = i * i + j;
+         A(i,j)=a; B(i,j)=b;
+      }
+      BandMatrix BA(7,2,4), BB(7,3,1), BC(7,2,1);
+      BA.Inject(A);
+      SymmetricBandMatrix SB(7,3);
+      SymmetricMatrix S; S << (B+B.t());
+      SB.Inject(S); A = BA; S = SB;
+      Matrix X;  
+      X = SP(BA,SB); X=X-SP(A,S); Print(X);
+      X = SP(BA*2,SB); X=X-SP(A,S*2); Print(X);
+      X = SP(BA,SB/4); X=X-SP(A/4,S); Print(X);
+      X = SP(BA*4,SB/4); X=X-SP(A,S); Print(X);
+      X = SP(BA,SB)-SP(A,S); Print(X);
+      X = SP(BA*2,SB)-SP(A,S*2); Print(X);
+      X = SP(BA,SB/4)-SP(A/4,S); Print(X);
+      X = SP(BA*4,SB/4)-SP(A,S); Print(X);
+   }
+
+}
+
+
Index: Shared/newmat/extra/tmtk.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtk.cpp
diff -N Shared/newmat/extra/tmtk.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtk.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,199 @@
+
+#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+static inline int my_min(int x, int y) { return x < y ? x : y; }
+static inline int my_max(int x, int y) { return x > y ? x : y; }
+
+
+#ifdef SETUP_C_SUBSCRIPTS
+
+void trymatk()
+{
+   Tracer et("Twentieth test of Matrix package");
+   Tracer::PrintTrace();
+   // test C subscript package
+
+
+   int i,j; Matrix X, Y;
+
+   cout << "Matrix\n";
+   Matrix A(15,35), B(15, 35);
+   for (i=0; i<15; i++) for (j=0; j<35; j++)
+      { A[i][j] = i+100*j; B(i+1,j+1) = i+100*j; }
+   X = A - B; Print(X); Y = X;
+   for (i=0; i<15; i++) for (j=0; j<35; j++)
+   {
+      X.element(i,j) = A.element(i,j) - B[i][j];
+      Y.element(i,j) = ((const Matrix&)A)[i][j] - B[i][j];
+   }
+   Print(X); Print(Y);
+   A.CleanUp(); B.CleanUp();
+
+   cout << "UpperTriangularMatrix\n";
+   UpperTriangularMatrix A1(15), B1(15);
+   for (i=0; i<15; i++) for (j=i; j<15; j++)
+      { A1[i][j] = i+100*j; B1(i+1,j+1) = i+100*j; }
+   X = A1 - B1; Print(X); Y = X;
+   for (i=0; i<15; i++) for (j=i; j<15; j++)
+   {
+      X.element(i,j) = A1.element(i,j) - B1[i][j];
+      Y.element(i,j) = ((const UpperTriangularMatrix&)A1)[i][j] - B1[i][j];
+   }
+   Print(X); Print(Y);
+   A1.CleanUp(); B1.CleanUp();
+
+   cout << "LowerTriangularMatrix\n";
+   LowerTriangularMatrix A2(35), B2(35); 
+   for (i=0; i<35; i++) for (j=0; j<=i; j++)
+      { A2[i][j] = i+100*j; B2(i+1,j+1) = i+100*j; }
+   X = A2 - B2; Print(X); Y = X;
+   for (i=0; i<35; i++) for (j=0; j<=i; j++)
+   {
+      X.element(i,j) = A2.element(i,j) - B2[i][j];
+      Y.element(i,j) = ((const LowerTriangularMatrix&)A2)[i][j] - B2[i][j];
+   }
+   Print(X); Print(Y);
+   A2.CleanUp(); B2.CleanUp();
+
+   cout << "SymmetricMatrix\n";
+   SymmetricMatrix A3(10), B3(10);
+   for (i=0; i<10; i++) for (j=0; j<=i; j++)
+      { A3[i][j] = i+100*j; B3(i+1,j+1) = i+100*j; }
+   X = A3 - B3; Print(X); Y = X;
+   for (i=0; i<10; i++) for (j=0; j<=i; j++)
+   {
+      X.element(i,j) = A3.element(i,j) - B3[i][j];
+      Y.element(i,j) = ((const SymmetricMatrix&)A3)[i][j] - B3[i][j];
+   }
+   Print(X); Print(Y);
+   A3.CleanUp(); B3.CleanUp();
+
+   cout << "DiagonalMatrix\n";
+   DiagonalMatrix A4(10), B4(10);
+   for (i=0; i<10; i++)
+      { A4[i] = i+100; B4(i+1) = i+100; }
+   X = A4 - B4; Print(X); Y = X;
+   for (i=0; i<10; i++)
+   {
+      X.element(i,i) = A4.element(i) - B4[i];
+      Y.element(i,i) = ((const DiagonalMatrix&)A4)[i] - B4[i];
+   }
+   Print(X); Print(Y);
+   A4.CleanUp(); B4.CleanUp();
+
+   cout << "RowVector\n";
+   RowVector A5(10), B5(10);
+   for (i=0; i<10; i++)
+      { A5[i] = i+100; B5(i+1) = i+100; }
+   X = A5 - B5; Print(X); Y = X;
+   for (i=0; i<10; i++)
+   {
+      X.element(0,i) = A5.element(i) - B5[i];
+      Y.element(0,i) = ((const RowVector&)A5)[i] - B5[i];
+   }
+   Print(X); Print(Y);
+   A5.CleanUp(); B5.CleanUp();
+
+   cout << "ColumnVector\n";
+   ColumnVector A6(10), B6(10);
+   for (i=0; i<10; i++)
+      { A6[i] = i+100; B6(i+1) = i+100; }
+   X = A6 - B6; Print(X); Y = X;
+   for (i=0; i<10; i++)
+   {
+      X.element(i,0) = A6.element(i) - B6[i];
+      Y.element(i,0) = ((const ColumnVector&)A6)[i] - B6[i];
+   }
+   Print(X); Print(Y);
+   A6.CleanUp(); B6.CleanUp();
+
+   cout << "BandMatrix\n";
+   BandMatrix A7(55,10, 5), B7(55, 10, 5);
+   for (i=0; i<55; i++) for (j=my_max(0,i-10); j<=my_min(54,i+5); j++)
+      { A7[i][j] = i+100*j; B7(i+1,j+1) = i+100*j; }
+   X = A7 - B7; Print(X); Y = X;
+   for (i=0; i<55; i++) for (j=my_max(0,i-10); j<=my_min(54,i+5); j++)
+   {
+      X.element(i,j) = A7.element(i,j) - B7[i][j];
+      Y.element(i,j) = ((const BandMatrix&)A7)[i][j] - B7[i][j];
+   }
+   Print(X); Print(Y);
+   A7.CleanUp(); B7.CleanUp();
+
+   cout << "UpperBandMatrix\n";
+   UpperBandMatrix A8(80,15), B8(80,15);
+   for (i=0; i<80; i++) for (j=i; j<=my_min(79,i+15); j++)
+      { A8[i][j] = i+100*j; B8(i+1,j+1) = i+100*j; }
+   X = A8 - B8; Print(X); Y = X;
+   for (i=0; i<80; i++) for (j=i; j<=my_min(79,i+15); j++)
+   {
+      X.element(i,j) = A8.element(i,j) - B8[i][j];
+      Y.element(i,j) = ((const UpperBandMatrix&)A8)[i][j] - B8[i][j];
+   }
+   Print(X); Print(Y);
+   A8.CleanUp(); B8.CleanUp();
+
+   cout << "LowerBandMatrix\n";
+   LowerBandMatrix A9(75,27), B9(75,27);
+   for (i=0; i<75; i++) for (j=my_max(0,i-27); j<=i; j++)
+      { A9[i][j] = i+100*j; B9(i+1,j+1) = i+100*j; }
+   X = A9 - B9; Print(X); Y = X;
+   for (i=0; i<75; i++) for (j=my_max(0,i-27); j<=i; j++)
+   {
+      X.element(i,j) = A9.element(i,j) - B9[i][j];
+      Y.element(i,j) = ((const LowerBandMatrix&)A9)[i][j] - B9[i][j];
+   }
+   Print(X); Print(Y);
+   A9.CleanUp(); B9.CleanUp();
+
+   cout << "SymmetricBandMatrix\n";
+   SymmetricBandMatrix Aa(69,15), Ba(69,15);
+   for (i=0; i<69; i++) for (j=my_max(0,i-15); j<=i; j++)
+      { Aa[i][j] = i+100*j; Ba(i+1,j+1) = i+100*j; }
+   X = Aa - Ba; Print(X); Y = X;
+   for (i=0; i<69; i++) for (j=my_max(0,i-15); j<=i; j++)
+   {
+      X.element(i,j) = Aa.element(i,j) - Ba[i][j];
+      Y.element(i,j) = ((const SymmetricBandMatrix&)Aa)[i][j] - Ba[i][j];
+   }
+   Print(X); Print(Y);
+   Aa.CleanUp(); Ba.CleanUp();
+   
+   // test special constructors used in Numerical Recipes for C++
+   Real a[] = {1.2, 5.6, 7.9, 3.8, 4.5, 1.3,
+               5.2, 9.9, 2.1, 4.7, 0.0, 1.6 };
+   ColumnVector CV0(12); CV0 << a;
+   ColumnVector CV1(a, 12); CV1 -= CV0; Print(CV1);
+   RowVector RV1(a, 12); RV1 -= CV0.AsRow(); Print(RV1);
+   Matrix RM1(a, 3, 4); RM1 -= CV0.AsMatrix(3,4); Print(RM1);
+   ColumnVector CV2(5.75, 15); CV2 -= 5.75; Print(CV2);
+   RowVector RV2(2.75, 15); RV2 -= 2.75; Print(RV2);
+   Matrix RM2(-3.75, 6, 4); RM2 += 3.75; Print(RM2);
+
+
+}
+
+
+#else
+
+void trymatk()
+{
+   Tracer et("Twentieth test of Matrix package");
+   Tracer::PrintTrace();
+   // test C subscript package
+   cout << "C subscripts not enabled, not tested\n\n";
+}
+
+#endif
Index: Shared/newmat/extra/tmtl.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtl.cpp
diff -N Shared/newmat/extra/tmtl.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtl.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,198 @@
+
+#define WANT_STREAM
+
+#define WANT_MATH
+
+#include "newmat.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+// test maxima and minima
+
+Real TestMax(const GenericMatrix& GM)
+{
+   Matrix M = GM;
+   ColumnVector CV = GM.AsColumn();
+
+   int c, i, j, k; int n = CV.Nrows(), nr = M.Nrows(), nc = M.Ncols();
+   Real x1, x2, x3;
+
+   MatrixBandWidth mbw = GM.BandWidth();
+   int u = mbw.Upper(); int l = mbw.Lower();
+   bool IsBandMatrix = u > 0 && l > 0 && !(u == 0 && l == 0);
+
+   x1 = GM.MaximumAbsoluteValue();
+   x2 = GM.MaximumAbsoluteValue1(i);
+   if (fabs(CV(i)) != x2) return 1.1;
+   x3 = GM.MaximumAbsoluteValue2(i,j);
+   if (fabs(M(i,j)) != x3) return 1.2;
+   if (x3 != x1) return 1.3;
+   if (x2 != x1) return 1.4;
+   c = 0;
+   for (k = 1; k <= n; k++)
+   {
+      Real cvk = fabs(CV(k));
+      if (x1 <= cvk) { if (x1 < cvk) return 1.5; else c++; }
+   }
+   if (c == 0) return 1.6;
+
+
+   x1 = GM.MinimumAbsoluteValue();
+   x2 = GM.MinimumAbsoluteValue1(i);
+   if (fabs(CV(i)) != x2) return 2.1;
+   x3 = GM.MinimumAbsoluteValue2(i,j);
+   if (fabs(M(i,j)) != x3) return 2.2;
+   if (x3 != x1) return 2.3;
+   if (x2 != CV.MinimumAbsoluteValue()) return 2.4;
+   c = 0;
+   if (IsBandMatrix)
+   {
+      for (i = 1; i <= nr; i++) for (j = 1; j <= nc; j++)
+         if (i - j <= l && j - i <= u)
+      {
+         Real mij = fabs(M(i,j));
+         if (x1 >= mij) { if (x1 > mij) return 2.51; else c++; }
+      }
+   }
+   else
+   {
+      for (k = 1; k <= n; k++)
+      {
+         Real cvk = fabs(CV(k));
+         if (x1 >= cvk) { if (x1 > cvk) return 2.52; else c++; }
+      }
+   }
+   if (c == 0) return 2.6;
+
+   x1 = GM.Maximum();
+   x2 = GM.Maximum1(i);
+   if (CV(i) != x2) return 3.1;
+   x3 = GM.Maximum2(i,j);
+   if (M(i,j) != x3) return 3.2;
+   if (x3 != x1) return 3.3;
+   if (x2 != CV.Maximum()) return 3.4;
+   c = 0;
+   if (IsBandMatrix)
+   {
+      for (i = 1; i <= nr; i++) for (j = 1; j <= nc; j++)
+         if (i - j <= l && j - i <= u)
+      {
+         Real mij = M(i,j);
+         if (x1 <= mij) { if (x1 < mij) return 3.51; else c++; }
+      }
+   }
+   else
+   {
+      for (k = 1; k <= n; k++)
+      {
+         Real cvk = CV(k);
+         if (x1 <= cvk) { if (x1 < cvk) return 3.52; else c++; }
+      }
+   }
+   if (c == 0) return 3.6;
+
+   x1 = GM.Minimum();
+   x2 = GM.Minimum1(i);
+   if (CV(i) != x2) return 4.1;
+   x3 = GM.Minimum2(i,j);
+   if (M(i,j) != x3) return 4.2;
+   if (x3 != x1) return 4.3;
+   if (x2 != CV.Minimum()) return 4.4;
+   c = 0;
+   if (IsBandMatrix)
+   {
+      for (i = 1; i <= nr; i++) for (j = 1; j <= nc; j++)
+         if (i - j <= l && j - i <= u)
+      {
+         Real mij = M(i,j);
+         if (x1 >= mij) { if (x1 > mij) return 4.51; else c++; }
+      }
+   }
+   else
+   {
+      for (k = 1; k <= n; k++)
+      {
+         Real cvk = CV(k);
+         if (x1 >= cvk) { if (x1 > cvk) return 4.52; else c++; }
+      }
+   }
+   if (c == 0) return 4.6;
+
+   return 0;
+
+}
+
+
+void trymatl()
+{
+   Tracer et("Twenty first test of Matrix package");
+   Tracer::PrintTrace();
+
+   Matrix M(4, 4);
+   M <<  1.5 <<  1.0 << -4.0 <<  4.5
+     <<  3.5 <<  7.0 <<  2.0 << -1.0
+     << -1.5 <<  7.5 << -6.0 <<  5.0
+     <<  0.5 << -8.0 <<  5.5 <<  4.0;
+   UpperTriangularMatrix UM;  UM << M;
+   LowerTriangularMatrix LM;  LM << -M;
+   SymmetricMatrix SM; SM << (UM + UM.t());
+   BandMatrix BM(4, 1, 2);  BM.Inject(M);
+   DiagonalMatrix DM; DM << M;
+   SymmetricBandMatrix SBM(4,1); SBM.Inject(M);
+   RowVector Test(28); int k = 0;
+
+   // tests for different shapes
+   Test(++k) = TestMax(GenericMatrix(M));
+   Test(++k) = TestMax(GenericMatrix(UM));
+   Test(++k) = TestMax(GenericMatrix(LM));
+   Test(++k) = TestMax(GenericMatrix(SM));
+   Test(++k) = TestMax(GenericMatrix(DM));
+   Test(++k) = TestMax(GenericMatrix(BM));
+   Test(++k) = TestMax(GenericMatrix(SBM));
+
+   // tests for constant matrices - don't put non-zeros in corners of BM
+   Matrix MX(4,4);
+   MX = 1; Test(++k) = TestMax(GenericMatrix(MX));
+   BM.Inject(MX); Test(++k) = TestMax(GenericMatrix(BM));
+   MX = 0; Test(++k) = TestMax(GenericMatrix(MX));
+   BM.Inject(MX); Test(++k) = TestMax(GenericMatrix(BM));
+   MX = -1; Test(++k) = TestMax(GenericMatrix(MX));
+   BM.Inject(MX); Test(++k) = TestMax(GenericMatrix(BM));
+
+   // test for non-square
+   MX = M | (2 * M).t(); Test(++k) = TestMax(GenericMatrix(MX));
+
+   // test on row and column vector
+   RowVector RV(6);
+   RV << 1 << 3 << -5 << 2 << -4 << 3;
+   Test(++k) = TestMax(GenericMatrix(RV));
+   Test(++k) = TestMax(GenericMatrix(RV.t()));
+
+   // test for function form
+   Test(++k) = (MaximumAbsoluteValue(RV) - 5);
+   Test(++k) = (MinimumAbsoluteValue(RV) - 1);
+   Test(++k) = (Maximum(RV) - 3);
+   Test(++k) = (Minimum(RV) + 5);
+   Test(++k) = (MaximumAbsoluteValue(-RV) - 5);
+   Test(++k) = (MinimumAbsoluteValue(-RV) - 1);
+   Test(++k) = (Maximum(-RV) - 5);
+   Test(++k) = (Minimum(-RV) + 3);
+
+   // test formulae
+   RowVector RV2(6);
+   RV2 << 2 << 8 << 1 << 9 << 3 << -1;
+   Test(++k) = (MaximumAbsoluteValue(RV+RV2) - 11);
+   Test(++k) = (MinimumAbsoluteValue(RV+RV2) - 1);
+   Test(++k) = (Maximum(RV+RV2) - 11);
+   Test(++k) = (Minimum(RV+RV2) + 4);
+
+
+   Print(Test);
+}
+
Index: Shared/newmat/extra/tmtm.cpp
===================================================================
RCS file: Shared/newmat/extra/tmtm.cpp
diff -N Shared/newmat/extra/tmtm.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Shared/newmat/extra/tmtm.cpp	16 Jun 2004 21:16:46 -0000	1.1
@@ -0,0 +1,271 @@
+
+#define WANT_STREAM
+
+#define WANT_MATH
+
+#include "newmat.h"
+#include "newmatio.h"
+
+#include "tmt.h"
+
+#ifdef use_namespace
+using namespace NEWMAT;
+#endif
+
+
+
+// test Kronecker Product
+
+
+void trymatm()
+{
+   Tracer et("Twenty second test of Matrix package");
+   Tracer::PrintTrace();
+
+   {
+      Tracer et1("Stage 1");
+
+
+      Matrix A(2,3);
+      A << 3 << 5 << 2
+        << 4 << 1 << 6;
+
+      Matrix B(4,3);
+      B <<  7 <<  2 <<  9
+        <<  1 <<  3 <<  6
+        <<  4 << 10 <<  5
+        << 11 <<  8 << 12;
+
+      Matrix C(8, 9);
+
+      C.Row(1) << 21 <<  6 << 27  << 35 << 10 << 45  << 14 <<  4 << 18;
+      C.Row(2) <<  3 <<  9 << 18  <<  5 << 15 << 30  <<  2 <<  6 << 12;
+      C.Row(3) << 12 << 30 << 15  << 20 << 50 << 25  <<  8 << 20 << 10;
+      C.Row(4) << 33 << 24 << 36  << 55 << 40 << 60  << 22 << 16 << 24;
+
+      C.Row(5) << 28 <<  8 << 36  <<  7 <<  2 <<  9  << 42 << 12 << 54;
+      C.Row(6) <<  4 << 12 << 24  <<  1 <<  3 <<  6  <<  6 << 18 << 36;
+      C.Row(7) << 16 << 40 << 20  <<  4 << 10 <<  5  << 24 << 60 << 30;
+      C.Row(8) << 44 << 32 << 48  << 11 <<  8 << 12  << 66 << 48 << 72;
+
+      Matrix AB = KP(A,B) - C; Print(AB);
+
+      IdentityMatrix I1(10); IdentityMatrix I2(15); I2 *= 2;
+      DiagonalMatrix D = KP(I1, I2) - IdentityMatrix(150) * 2;
+      Print(D);
+   }
+
+   {
+      Tracer et1("Stage 2");
+
+      UpperTriangularMatrix A(3);
+      A << 3 << 8 << 5
+             << 7 << 2
+                  << 4;
+      UpperTriangularMatrix B(4);
+      B << 4 << 1 << 7 << 2
+             << 3 << 9 << 8
+                  << 1 << 5
+                       << 6;
+
+      UpperTriangularMatrix C(12);
+
+      C.Row(1) <<12<< 3<<21<< 6 <<32<< 8<<56<<16 <<20<< 5<<35<<10;
+      C.Row(2)     << 9<<27<<24 << 0<<24<<72<<64 << 0<<15<<45<<40;
+      C.Row(3)         << 3<<15 << 0<< 0<< 8<<40 << 0<< 0<< 5<<25;
+      C.Row(4)             <<18 << 0<< 0<< 0<<48 << 0<< 0<< 0<<30;
+
+      C.Row(5)                  <<28<< 7<<49<<14 << 8<< 2<<14<< 4;
+      C.Row(6)                      <<21<<63<<56 << 0<< 6<<18<<16;
+      C.Row(7)                          << 7<<35 << 0<< 0<< 2<<10;
+      C.Row(8)                              <<42 << 0<< 0<< 0<<12;
+
+      C.Row(9)                                   <<16<< 4<<28<< 8;
+      C.Row(10)                                      <<12<<36<<32;
+      C.Row(11)                                          << 4<<20;
+      C.Row(12)                                              <<24;
+
+
+      UpperTriangularMatrix AB = KP(A,B) - C; Print(AB);
+
+      LowerTriangularMatrix BT = B.t(); Matrix N(12,12);
+
+      N.Row(1) <<12 << 0<< 0<< 0 <<32<< 0<< 0<< 0 <<20<< 0<< 0<< 0;
+      N.Row(2) << 3 << 9<< 0<< 0 << 8<<24<< 0<< 0 << 5<<15<< 0<< 0;
+      N.Row(3) <<21 <<27<< 3<< 0 <<56<<72<< 8<< 0 <<35<<45<< 5<< 0;
+      N.Row(4) << 6 <<24<<15<<18 <<16<<64<<40<<48 <<10<<40<<25<<30;
+
+      N.Row(5) << 0 << 0<< 0<< 0 <<28<< 0<< 0<< 0 << 8<< 0<< 0<< 0;
+      N.Row(6) << 0 << 0<< 0<< 0 << 7<<21<< 0<< 0 << 2<< 6<< 0<< 0;
+      N.Row(7) << 0 << 0<< 0<< 0 <<49<<63<< 7<< 0 <<14<<18<< 2<< 0;
+      N.Row(8) << 0 << 0<< 0<< 0 <<14<<56<<35<<42 << 4<<16<<10<<12;
+
+      N.Row(9) << 0 << 0<< 0<< 0 << 0<< 0<< 0<< 0 <<16<< 0<< 0<< 0;
+      N.Row(10)<< 0 << 0<< 0<< 0 << 0<< 0<< 0<< 0 << 4<<12<< 0<< 0;
+      N.Row(11)<< 0 << 0<< 0<< 0 << 0<< 0<< 0<< 0 <<28<<36<< 4<< 0;
+      N.Row(12)<< 0 << 0<< 0<< 0 << 0<< 0<< 0<< 0 << 8<<32<<20<<24;
+
+      Matrix N1 = KP(A, BT); N1 -= N; Print(N1);
+      AB << KP(A, BT); AB << (AB - N); Print(AB);
+      BT << KP(A, BT); BT << (BT - N); Print(BT);
+
+      LowerTriangularMatrix AT = A.t();
+      N1 = KP(AT, B); N1 -= N.t(); Print(N1);
+      AB << KP(AT, B); AB << (AB - N.t()); Print(AB);
+      BT << KP(AT, B); BT << (BT - N.t()); Print(BT);
+   }
+
+   {
+      Tracer et1("Stage 3");
+
+      BandMatrix BMA(6,2,3);
+      BMA.Row(1) << 5.25 << 4.75 << 2.25 << 1.75;
+      BMA.Row(2) << 1.25 << 9.75 << 4.50 << 0.25 << 1.50;
+      BMA.Row(3) << 7.75 << 1.50 << 3.00 << 4.25 << 0.50 << 5.50;
+      BMA.Row(4) << 2.75 << 9.00 << 8.00 << 3.25 << 3.50;
+      BMA.Row(5) << 8.75 << 6.25 << 5.00 << 5.75;
+      BMA.Row(6) << 3.75 << 6.75 << 6.00;
+
+      Matrix A = BMA;
+
+      BandMatrix BMB(4,2,1);
+      BMB.Row(1) << 4.5 << 9.5;
+      BMB.Row(2) << 1.5 << 6.0 << 2.0;
+      BMB.Row(3) << 0.5 << 2.5 << 8.5 << 7.5;
+      BMB.Row(4) << 3.0 << 4.0 << 6.5;
+
+      SquareMatrix B = BMB;
+
+      BandMatrix BMC = KP(BMA, BMB);
+      BandMatrix BMC1 = KP(BMA, B);
+      Matrix C2 = KP(A, BMB);
+      Matrix C = KP(A, B);
+
+      Matrix M = C - BMC; Print(M);
+      M = C - BMC1; Print(M);
+      M = C - C2; Print(M);
+
+      RowVector X(4);
+      X(1) = BMC.BandWidth().Lower() - 10;
+      X(2) = BMC.BandWidth().Upper() - 13;
+      X(3) = BMC1.BandWidth().Lower() - 11;
+      X(4) = BMC1.BandWidth().Upper() - 15;
+      Print(X);
+
+      UpperTriangularMatrix UT;  UT << KP(BMA, BMB);
+      UpperTriangularMatrix UT1; UT1 << (C - UT); Print(UT1);
+      LowerTriangularMatrix LT;  LT << KP(BMA, BMB);
+      LowerTriangularMatrix LT1; LT1 << (C - LT); Print(LT1);
+   }
+
+   {
+      Tracer et1("Stage 4");
+
+      SymmetricMatrix SM1(4);
+      SM1.Row(1) << 2;
+      SM1.Row(2) << 4 << 5;
+      SM1.Row(3) << 9 << 2 << 1;
+      SM1.Row(4) << 3 << 6 << 8 << 2;
+
+      SymmetricMatrix SM2(3);
+      SM2.Row(1) <<  3;
+      SM2.Row(2) << -7 << -6;
+      SM2.Row(3) <<  4 << -2 << -1;
+
+      SymmetricMatrix SM = KP(SM1, SM2);
+      Matrix M1 = SM1; Matrix M2 = SM2;
+      Matrix M = KP(SM1, SM2); M -= SM; Print(M);
+      M = KP(SM1, SM2) - SM; Print(M);
+      M = KP(M1, SM2) - SM; Print(M);
+      M = KP(SM1, M2) - SM; Print(M);
+      M = KP(M1, M2); M -= SM; Print(M);
+   }
+
+   {
+      Tracer et1("Stage 5");
+
+      Matrix A(2,3);
+      A << 3 << 5 << 2
+        << 4 << 1 << 6;
+
+      Matrix B(3,4);
+      B <<  7 <<  2 <<  9 << 11
+        <<  1 <<  3 <<  6 <<  8
+        <<  4 << 10 <<  5 << 12;
+
+      RowVector C(2); C << 3 << 7;
+      ColumnVector D(4); D << 0 << 5 << 13 << 11;
+
+      Matrix M = KP(C * A, B * D) - KP(C, B) * KP(A, D); Print(M);
+   }
+
+   {
+      Tracer et1("Stage 6");
+
+      RowVector A(3), B(5), C(15);
+      A << 5 << 2 << 4;
+      B << 3 << 2 << 0 << 1 << 6;
+      C << 15 << 10 << 0 << 5 << 30
+        <<  6 <<  4 << 0 << 2 << 12
+        << 12 <<  8 << 0 << 4 << 24;
+      Matrix N = KP(A, B) - C;    Print(N);
+      N = KP(A.t(), B.t()) - C.t();    Print(N);
+      N = KP(A.AsDiagonal(), B.AsDiagonal()) - C.AsDiagonal();    Print(N);
+   }
+
+   {
+      Tracer et1("Stage 7");
+      IdentityMatrix I(3);
+      ColumnVector CV(4); CV << 4 << 3 << 1 << 7;
+      Matrix A = KP(I, CV) + 5;
+      Matrix B(3,12);
+      B.Row(1) << 9 << 8 << 6 << 12 << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 5;
+      B.Row(2) << 5 << 5 << 5 << 5 << 9 << 8 << 6 << 12 << 5 << 5 << 5 << 5;
+      B.Row(3) << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 9 << 8 << 6 << 12;
+      B -= A.t(); Print(B);
+
+   }
+
+   {
+      Tracer et1("Stage 8");          // SquareMatrix
+      Matrix A(2,3), B(3,2);
+      A << 2 << 6 << 7
+        << 4 << 3 << 9;
+      B << 1 << 3
+        << 4 << 8
+        << 0 << 6;
+      SquareMatrix AB = A * B;
+      Matrix M = (B.t() * A.t()).t(); M -= AB; Print(M);
+      AB = B * A;
+      M = (A.t() * B.t()).t(); M -= AB; Print(M);
+      AB.ReSize(5,5); AB = 0;
+      AB.SubMatrix(1,2,1,3) = A; AB.SubMatrix(4,5,3,5) = A;
+      AB.SubMatrix(1,3,4,5) = B; AB.SubMatrix(3,5,1,2) = B;
+      SquareMatrix C(5);
+      C.Row(1) << 2 << 6 << 7 << 1 << 3;
+      C.Row(2) << 4 << 3 << 9 << 4 << 8;
+      C.Row(3) << 1 << 3 << 0 << 0 << 6;
+      C.Row(4) << 4 << 8 << 2 << 6 << 7;
+      C.Row(5) << 0 << 6 << 4 << 3 << 9;
+      C -= AB; Print(C);
+      AB = A.SymSubMatrix(1,2);
+      AB = (AB | AB) & (AB | AB);
+      C.ReSize(4);
+      C.Row(1) << 2 << 6 << 2 << 6;
+      C.Row(2) << 4 << 3 << 4 << 3;
+      C.Row(3) << 2 << 6 << 2 << 6;
+      C.Row(4) << 4 << 3 << 4 << 3;
+      M = AB;
+      C -= M; Print(C);
+      C << M; C += -M; Print(C);
+      
+   }
+
+
+}
+
+
+
+
+
+
Index: SoundPlay/SoundManager.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/SoundPlay/SoundManager.cc,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- SoundPlay/SoundManager.cc	25 Jul 2003 20:18:08 -0000	1.14
+++ SoundPlay/SoundManager.cc	8 Oct 2004 00:07:25 -0000	1.15
@@ -27,12 +27,9 @@
 
 //!@todo this does one more copy than it really needs to
 SoundManager::Snd_ID
-SoundManager::LoadFile(const char* name) {
-	if(name==NULL || name[0]=='\0')
-		return invalid_Snd_ID;
+SoundManager::LoadFile(std::string const &name) {
 	AutoLock autolock(lock,ProcessID::getID());
-	char tmp[MAX_NAME_LEN];
-	const char* path=makePath(name,tmp);
+	std::string path(config->sound.makePath(name));
 	Snd_ID id=lookupPath(path);
 	if(id!=invalid_Snd_ID) {
 		//		cout << "add reference to pre-existing" << endl;
@@ -40,12 +37,12 @@
 	} else {
 		//		cout << "load new file" << endl;
 		struct stat buf;
-		if(stat(path,&buf)==-1) {
-			cout << "SoundManager::LoadFile(): Sound file not found " << path << endl;
+		if(stat(path.c_str(),&buf)==-1) {
+			cout << "SoundManager::LoadFile(): Sound file not found " << name << endl;
 			return invalid_Snd_ID;
 		}
 		byte * sndbuf=new byte[buf.st_size];
-		std::ifstream file(path);
+		std::ifstream file(path.c_str());
 		file.read(reinterpret_cast<char*>(sndbuf),buf.st_size);
 		WAV wav;
 		WAVError error = wav.Set(sndbuf);
@@ -59,7 +56,7 @@
 		}
 		id=LoadBuffer(reinterpret_cast<char*>(wav.GetDataStart()),wav.GetDataEnd()-wav.GetDataStart());
 		delete [] sndbuf;
-		strncpy(sndlist[id].name,path,MAX_NAME_LEN);
+		strncpy(sndlist[id].name,path.c_str(),MAX_NAME_LEN);
 	}
 	return id;
 }
@@ -103,11 +100,9 @@
 }
 	
 void
-SoundManager::ReleaseFile(const char* name) {
-	if(name==NULL || name[0]=='\0')
-		return;
+SoundManager::ReleaseFile(std::string const &name) {
 	AutoLock autolock(lock,ProcessID::getID());
-	Release(lookup(name));
+	Release(lookupPath(name));
 }
 
 void
@@ -140,8 +135,8 @@
 }
 
 SoundManager::Play_ID
-SoundManager::PlayFile(const char* name) {
-	if(playlist.size()>=playlist_t::MAX_ENTRIES || name==NULL || name[0]=='\0')
+SoundManager::PlayFile(std::string const &name) {
+  if(playlist.size()>=playlist_t::MAX_ENTRIES)
 		return invalid_Play_ID;	
 	AutoLock autolock(lock,ProcessID::getID());
 	Snd_ID sndid=LoadFile(name);
@@ -198,8 +193,8 @@
 }
 	
 SoundManager::Play_ID
-SoundManager::ChainFile(Play_ID base, const char * next) {
-	if(base==invalid_Play_ID || next==NULL || next[0]=='\0')
+SoundManager::ChainFile(Play_ID base, std::string const &next) {
+       if(base==invalid_Play_ID)
 		return base;
 	Play_ID orig=base;
 	while(playlist[base].next_id!=invalid_Play_ID)
@@ -545,31 +540,14 @@
 }
 
 SoundManager::Snd_ID 
-SoundManager::lookup(const char* name) const {
-	char tmp[MAX_NAME_LEN];
-	return lookupPath(makePath(name,tmp));
-}
-SoundManager::Snd_ID 
-SoundManager::lookupPath(const char* path) const {
+SoundManager::lookupPath(std::string const &name) const {
+        std::string const path(config->sound.makePath(name));
 	for(sndlist_t::index_t it=sndlist.begin(); it!=sndlist.end(); it=sndlist.next(it))
-		if(strncasecmp(path,sndlist[it].name,MAX_NAME_LEN)==0)
+		if(strncasecmp(path.c_str(),sndlist[it].name,MAX_NAME_LEN)==0)
 			return it;
 	return invalid_Snd_ID;
 }
 
-const char*
-SoundManager::makePath(const char* name, char tmp[MAX_NAME_LEN]) {
-	const char* path=name;
-	if(name[0]!='/') {
-		path=tmp;
-		strncpy(tmp,config->sound.root.c_str(),MAX_NAME_LEN);
-		strncat(tmp,"/",MAX_NAME_LEN);
-		strncat(tmp,name,MAX_NAME_LEN);
-	}
-	//	cout << name << " is " << path << endl;
-	return path;
-}
-
 void
 SoundManager::selectChannels(std::vector<Play_ID>& mix) {
 	unsigned int selected=0;
@@ -687,11 +665,11 @@
  * @brief Implements SoundManager, which provides sound effects and caching services, as well as mixing buffers for the SoundPlay process
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.14 $
- * $State: Rel $
- * $Date: 2003/07/25 20:18:08 $
+ * $Revision: 1.15 $
+ * $State: Exp $
+ * $Date: 2004/10/08 00:07:25 $
  */
 
 
Index: SoundPlay/SoundManager.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/SoundPlay/SoundManager.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- SoundPlay/SoundManager.h	9 Feb 2004 22:45:28 -0000	1.11
+++ SoundPlay/SoundManager.h	8 Oct 2004 00:07:25 -0000	1.12
@@ -87,7 +87,7 @@
 	 * @param name can be either a full path, or a partial path relative to Config::sound_config::root
 	 * @return ID number for future references (can also use name)
 	 * The sound data will be cached until ReleaseFile() or Release() is called a matching number of times*/
-	Snd_ID LoadFile(const char* name);
+	Snd_ID LoadFile(std::string const &name);
 
 	//!loads raw samples from a buffer (assumes matches Config::sound_config settings)
 	/*!The sound data will be cached until Release() is called a matching number of times.\n
@@ -95,7 +95,7 @@
 	Snd_ID LoadBuffer(const char buf[], unsigned int len);
 	
 	//!Marks the sound buffer to be released after the last play command completes (or right now if not being played)
-	void ReleaseFile(const char* name);
+	void ReleaseFile(std::string const &name);
 
 	//!Marks the sound buffer to be released after the last play command completes (or right now if not being played)
 	void Release(Snd_ID id);
@@ -105,7 +105,7 @@
 	 * @param name can be either a full path, or a partial path relative to Config::sound_config::root
 	 * @return ID number for future references
 	 * The sound data will not be cached after done playing unless a call to LoadFile is made*/
-	Play_ID PlayFile(const char* name);
+	Play_ID PlayFile(std::string const &name);
 
 	//!loads raw samples from a buffer (assumes buffer matches Config::sound_config settings)
 	/*!The sound data will be released after done playing*/
@@ -118,7 +118,7 @@
 	/*!if you chain more than once to the same base, the new buffers are appended
 	 * to the end of the chain - the new buffer doesn't replace the current chain
 	 * @return @a base - just for convenience of multiple calls*/
-	Play_ID ChainFile(Play_ID base, const char* next);
+	Play_ID ChainFile(Play_ID base, std::string const &next);
 
 	//!allows automatic queuing of sounds - good for dynamic sound sources!
 	/*!if you chain more than once to the same base, the new buffers are appended
@@ -173,13 +173,8 @@
 	//!Sets up a shared region to hold a sound - rounds to nearest page size
 	static RCRegion* initRegion(unsigned int size);
 
-	//!Looks to see if @a name matches any of the sounds in sndlist
-	Snd_ID lookup(const char* name) const;
-	//!Looks to see if @a name matches any of the sounds in sndlist (assumes is absolute path)
-	Snd_ID lookupPath(const char* path) const;
-
-	//!prepends config.sound.root to the name if necessary
-	static const char* makePath(const char* name, char tmp[MAX_NAME_LEN]);
+	//!Looks to see if @a name matches any of the sounds in sndlist (converts to absolute path if not already)
+	Snd_ID lookupPath(std::string const &name) const;
 
 	//!selects which of the channels are actually to be mixed together, depending on queue_mode
 	void selectChannels(std::vector<Play_ID>& mix);
@@ -250,11 +245,11 @@
  * @brief Describes SoundManager, which provides sound effects and caching services, as well as mixing buffers for the SoundPlay process
  * @author ejt (Creator)
  *
- * $Author: ejt $
+ * $Author: dst $
  * $Name:  $
- * $Revision: 1.11 $
+ * $Revision: 1.12 $
  * $State: Exp $
- * $Date: 2004/02/09 22:45:28 $
+ * $Date: 2004/10/08 00:07:25 $
  */
 
 #endif
Index: TinyFTPD/FtpConfig.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpConfig.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- TinyFTPD/FtpConfig.h	30 Sep 2002 18:19:48 -0000	1.1.1.1
+++ TinyFTPD/FtpConfig.h	6 Jul 2004 22:30:57 -0000	1.2
@@ -1,8 +1,12 @@
 //
-// FtpConfig.h
+// Copyright 2002,2003 Sony Corporation 
 //
-// Copyright 2001 Sony Corporation
+// Permission to use, copy, modify, and redistribute this software for
+// non-commercial use is hereby granted.
 //
+// This software is provided "as is" without warranty of any kind,
+// either expressed or implied, including but not limited to the
+// implied warranties of fitness for a particular purpose.
 //
 
 #ifndef _FtpConfig_h_DEFINED
@@ -10,7 +14,8 @@
 
 #define FTP_LISTEN_PORT    21
 #define FTP_DATA_PORT      20
-#define FTP_CONNECTION_MAX 1
+#define FTP_PASV_DATA_PORT 3000
+#define FTP_CONNECTION_MAX 4
 #define FTP_BUFFER_SIZE    8192
 #define FTP_PASSWD_PATH    "/MS/OPEN-R/MW/CONF/PASSWD"
 #define MAX_STRING_LENGTH  128
@@ -29,11 +34,10 @@
     char pass[MAX_STRING_LENGTH];
     char home[MAX_STRING_LENGTH];
 
-    Passwd()
-    {
+    Passwd() {
         user[0] = '\0';
         pass[0] = '\0';
-        user[0] = '\0';
+        home[0] = '\0';
     }
 };
 
@@ -41,6 +45,7 @@
     FTP_NOT_LOGIN,
     FTP_LOGIN,
     FTP_GET_REQUEST,
+    FTP_UNDEF
 };
 
 enum FTPDataType {
@@ -94,6 +99,7 @@
     FTP_REPLY_SUPERFLUOUS     = 202,
     FTP_REPLY_SYSTEM_STATUS   = 211,
     FTP_REPLY_HELP_MESSAGE    = 214,
+    FTP_REPLY_SYSTEM_TYPE     = 215,
     FTP_REPLY_SERVICE_READY   = 220,
     FTP_REPLY_SERVICE_CLOSE   = 221,
     FTP_REPLY_CLOSE_DATA      = 226,
Index: TinyFTPD/FtpDTP.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpDTP.cc,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- TinyFTPD/FtpDTP.cc	25 Jul 2003 20:18:08 -0000	1.2
+++ TinyFTPD/FtpDTP.cc	6 Jul 2004 22:43:45 -0000	1.4
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -10,25 +10,27 @@
 //
 
 #include <OPENR/OSyslog.h>
+#include <OPENR/ODebug.h>
 #include "FtpDTP.h"
-#include "entry.h"
 
 FtpDTP::FtpDTP()
 {
 }
 
 OStatus
-FtpDTP::Initialize(const OID& myoid, const OID& ipoid, void* index)
+FtpDTP::Initialize(const OID& myoid, const antStackRef& ipstack, void* index)
 {
     OSYSDEBUG(("FtpDTP::Initialize()\n"));
 
     myOID        = myoid;
-    ipstackOID   = ipoid;
+    ipstackRef   = ipstack;
     continuation = index;
 
     // initialize FTP connection
     method   = FTP_METHOD_NOOP;
     dataType = FTP_DATA_A;
+    passive  = false;
+    connectPort = FTP_DATA_PORT;
 
     // initialize File System
     ResetFilename();
@@ -41,7 +43,7 @@
     //
     antEnvCreateSharedBufferMsg sendBufferMsg(FTP_BUFFER_SIZE);
 
-    sendBufferMsg.Call(ipstackOID, sizeof(sendBufferMsg));
+    sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
     if (sendBufferMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpDTP::Initialize()",
@@ -59,7 +61,7 @@
     //
     antEnvCreateSharedBufferMsg recvBufferMsg(FTP_BUFFER_SIZE);
 
-    recvBufferMsg.Call(ipstackOID, sizeof(recvBufferMsg));
+    recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
     if (recvBufferMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpDTP::Initialize()",
@@ -76,6 +78,44 @@
 }
 
 OStatus
+FtpDTP::Listen()
+{
+    OSYSDEBUG(("FtpDTP::Listen()\n"));
+
+    if (connection.state != CONNECTION_CLOSED) return oFAIL;
+
+    //
+    // Create endpoint
+    //
+    antEnvCreateEndpointMsg tcpCreateMsg(EndpointType_TCP,
+                                         FTP_BUFFER_SIZE * 2);
+
+    tcpCreateMsg.Call(ipstackRef, sizeof(tcpCreateMsg));
+    if (tcpCreateMsg.error != ANT_SUCCESS) {
+        OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
+                  "FtpDTP::Listen()",
+                  "Can't create endpoint",
+                  (int)continuation, tcpCreateMsg.error));
+        return oFAIL;
+    }
+    connection.endpoint = tcpCreateMsg.moduleRef;
+
+    //
+    // Listen
+    //
+    TCPEndpointListenMsg listenMsg(connection.endpoint,
+                                   IP_ADDR_ANY, connectPort);
+    listenMsg.continuation = continuation;
+
+    listenMsg.Send(ipstackRef, myOID,
+                   Extra_Entry[entryListenContforDTP], sizeof(listenMsg));
+    
+    connection.state = CONNECTION_LISTENING;
+
+    return oSUCCESS;
+}
+
+OStatus
 FtpDTP::Connect()
 {
     OSYSDEBUG(("FtpDTP::Connect()\n"));
@@ -88,7 +128,7 @@
     antEnvCreateEndpointMsg tcpCreateMsg(EndpointType_TCP,
                                          FTP_BUFFER_SIZE * 2);
 
-    tcpCreateMsg.Call(ipstackOID, sizeof(tcpCreateMsg));
+    tcpCreateMsg.Call(ipstackRef, sizeof(tcpCreateMsg));
     if (tcpCreateMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpDTP::Connect()",
@@ -106,7 +146,7 @@
                                      connectIP, connectPort);
     connectMsg.continuation = continuation;
 
-    connectMsg.Send(ipstackOID, myOID,
+    connectMsg.Send(ipstackRef, myOID,
                     Extra_Entry[entryConnectContforDTP], sizeof(connectMsg));
     
     connection.state = CONNECTION_CONNECTING;
@@ -115,6 +155,49 @@
 }
 
 bool
+FtpDTP::ListenCont(TCPEndpointListenMsg* listenMsg)
+{
+    OSYSDEBUG(("FtpDTP::ListenCont() %x %d - %x %d\n",
+               listenMsg->lAddress,
+               listenMsg->lPort,
+               listenMsg->fAddress,
+               listenMsg->fPort
+               ));
+
+    if (listenMsg->error != TCP_SUCCESS) {
+        OSYSLOG1((osyslogERROR, "%s : %s %d",
+                  "FtpDTP::ListenCont()",
+                  "FAILED. listenMsg->error", listenMsg->error));
+        Close();
+        return false;
+    }
+
+    connection.state = CONNECTION_CONNECTED;
+
+    switch (method) {
+    case FTP_METHOD_RETR:
+        RetrieveSend();
+        break;
+
+    case FTP_METHOD_STOR:
+        connection.recvSize = 0;
+        Receive();
+        break;
+
+    case FTP_METHOD_LIST:
+        if (!ListSend()) {
+            Close();
+        }
+        break;
+    default:
+        OSYSDEBUG(("not yet\n"));
+        break;
+    }
+
+    return true;
+}
+
+bool
 FtpDTP::ConnectCont(TCPEndpointConnectMsg* connectMsg)
 {
     OSYSDEBUG(("FtpDTP::ConnectCont()\n"));
@@ -129,8 +212,7 @@
 
     connection.state = CONNECTION_CONNECTED;
 
-		//CHANGE_ET - cast to int to avoid warning
-    switch ((int)method) {
+    switch (method) {
     case FTP_METHOD_RETR:
         RetrieveSend();
         break;
@@ -145,6 +227,7 @@
             Close();
         }
         break;
+    default:;//CHANGE_ET added default case to avoid unhandled enumeration warnings
     }
     return true;
 }
@@ -152,16 +235,18 @@
 OStatus
 FtpDTP::Send()
 {
-    OSYSDEBUG(("FtpDTP::Send() %d\n", connection.sendSize));
+    OSYSDEBUG(("FtpDTP::Send() "));
 
     if (connection.state != CONNECTION_CONNECTED) return oFAIL;
 
+    OSYSDEBUG(("%d\n", connection.sendSize));
+
     TCPEndpointSendMsg sendMsg(connection.endpoint,
                                connection.sendData,
                                connection.sendSize);
     sendMsg.continuation = continuation;
 
-    sendMsg.Send(ipstackOID, myOID,
+    sendMsg.Send(ipstackRef, myOID,
                  Extra_Entry[entrySendContforDTP],
                  sizeof(TCPEndpointSendMsg));
 
@@ -227,7 +312,7 @@
                                      1, FTP_BUFFER_SIZE);
     receiveMsg.continuation = continuation;
 
-    receiveMsg.Send(ipstackOID, myOID,
+    receiveMsg.Send(ipstackRef, myOID,
                     Extra_Entry[entryReceiveContforDTP], sizeof(receiveMsg));
 
     connection.state = CONNECTION_RECEIVING;
@@ -259,13 +344,14 @@
     connection.state = CONNECTION_CONNECTED;
     connection.recvSize = 0;
     Receive();
+
     return false;
 }
 
 OStatus
 FtpDTP::Close()
 {
-    OSYSDEBUG(("FtpDTP::Close()\n"));
+    OSYSDEBUG(("FtpDTP::Close() %d\n", connection.state));
 
     if (connection.state == CONNECTION_CLOSED
         || connection.state == CONNECTION_CLOSING) return oFAIL;
@@ -273,17 +359,21 @@
     TCPEndpointCloseMsg closeMsg(connection.endpoint);
     closeMsg.continuation = continuation;
 
-    closeMsg.Send(ipstackOID, myOID,
+    closeMsg.Send(ipstackRef, myOID,
                   Extra_Entry[entryCloseContforDTP], sizeof(closeMsg));
 
     connection.state = CONNECTION_CLOSING;
     ResetFilename();
+    method   = FTP_METHOD_NOOP;
+    dataType = FTP_DATA_A;
+    passive  = false;
+    connectPort = FTP_DATA_PORT;
 
     return oSUCCESS;
 }
 
 void
-FtpDTP::CloseCont(TCPEndpointCloseMsg* /*closeMsg*/)
+FtpDTP::CloseCont(TCPEndpointCloseMsg* /*closeMsg*/) //CHANGE_ET unused parameter
 {
     OSYSDEBUG(("FtpDTP::CloseCont()\n"));
     
Index: TinyFTPD/FtpDTP.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpDTP.h,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- TinyFTPD/FtpDTP.h	25 Jul 2003 20:18:08 -0000	1.2
+++ TinyFTPD/FtpDTP.h	6 Jul 2004 22:43:45 -0000	1.4
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -12,19 +12,25 @@
 #ifndef _FtpDTP_h_DEFINED
 #define _FtpDTP_h_DEFINED
 
+#include <stdio.h>
 #include <dirent.h>
 #include <EndpointTypes.h>
 #include <TCPEndpointMsg.h>
 #include "TCPConnection.h"
 #include "FtpConfig.h"
 
+#include "entry.h"
+#include "def.h"
+
 class FtpDTP
 {
 public:
     FtpDTP();
     virtual ~FtpDTP() {}
 
-    OStatus Initialize(const OID& myoid, const OID& ipoid, void* index);
+    OStatus Initialize(const OID& myoid,
+                       const antStackRef& ipstack, void* index);
+    bool ListenCont (TCPEndpointListenMsg*  listenMsg);
     bool ConnectCont(TCPEndpointConnectMsg* connectMsg);
     bool SendCont   (TCPEndpointSendMsg*    sendMsg);
     bool ReceiveCont(TCPEndpointReceiveMsg* receiveMsg);
@@ -46,6 +52,7 @@
     char * GetUser() {return ftpUser;};
 
     // Method
+    Port SetIP   (IPAddress ip);
     bool SetPort (char* ipport);
     bool Retrieve(char* filename);
     bool Store   (char* filename);
@@ -59,6 +66,7 @@
     void ResetFilename();
 
 private:
+    OStatus Listen ();
     OStatus Connect();
     OStatus Send   ();
     OStatus Receive();
@@ -69,12 +77,13 @@
     bool ListSend();
 
     OID myOID;
-    OID ipstackOID;
+    antStackRef ipstackRef;
 
     // connection info
     IPAddress connectIP;
     Port      connectPort;
     FTPMethod method;
+    bool passive;
 
     // File Info
     FTPDataType dataType;
@@ -83,13 +92,15 @@
     char ftpDir[MAX_STRING_LENGTH];
     char ftpFile[MAX_STRING_LENGTH];
     bool listLong;
+    bool total;
     FILE* fp;
     DIR*  dirp;
-    
+
     void* continuation;
     TCPConnection connection;
 
-		FtpDTP(const FtpDTP&); //!< don't call
-		FtpDTP& operator=(const FtpDTP&); //!< don't call
+		FtpDTP(const FtpDTP&); //CHANGE_ET copy constructor, don't call
+		FtpDTP operator=(const FtpDTP&); //CHANGE_ET assignment operator, don't call
 };
+
 #endif /* _FtpDTP_h_DEFINED */
Index: TinyFTPD/FtpMethod.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpMethod.cc,v
retrieving revision 1.2
retrieving revision 1.5
diff -u -d -r1.2 -r1.5
--- TinyFTPD/FtpMethod.cc	25 Jul 2003 20:18:08 -0000	1.2
+++ TinyFTPD/FtpMethod.cc	12 Jul 2004 19:58:59 -0000	1.5
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -12,9 +12,21 @@
 #include <sys/stat.h>
 #include <sys/unistd.h>
 #include <OPENR/OSyslog.h>
+#include <OPENR/ODebug.h>
 #include <OPENR/OCalendarTime.h>
 #include <stdlib.h>
 #include "FtpDTP.h"
+#include <stdio.h>
+
+Port 
+FtpDTP::SetIP(IPAddress ip)
+{
+    connectIP = ip;
+    connectPort = FTP_PASV_DATA_PORT + (int)continuation;
+    passive = true;
+    Listen();
+    return connectPort;
+}
 
 bool
 FtpDTP::SetPort(char* ipport)
@@ -55,6 +67,7 @@
     OSYSDEBUG(("FtpDTP::Port():Set IP:%x Port:%d\n", ip, port));
     connectIP   = (IPAddress)ip;
     connectPort = (Port)port;
+    passive = false;
     return true;
 }
 
@@ -83,7 +96,14 @@
 
     strncpy(ftpFile, filename, MAX_STRING_LENGTH);
 
-    Connect();
+    if (passive) {
+        if (connection.state == CONNECTION_CONNECTED) {
+            connection.recvSize = 0;
+            Receive();
+        }
+    } else {
+        Connect();
+    }
     return true;
 }
 
@@ -112,7 +132,13 @@
 
     strncpy(ftpFile, filename, MAX_STRING_LENGTH);
 
-    Connect();
+    if (passive) {
+        if (connection.state == CONNECTION_CONNECTED) {
+            RetrieveSend();
+        }
+    } else {
+        Connect();
+    }
     return true;
 }
 
@@ -122,7 +148,6 @@
     if (dataType == FTP_DATA_A) {
        connection.recvSize
            = fread(connection.recvData, 1, FTP_BUFFER_SIZE / 2, fp);
-
        if (FTP_BUFFER_SIZE / 2 > connection.recvSize) {
             byte *cur_r = connection.recvData;
             byte *cur_s = connection.sendData;
@@ -163,7 +188,6 @@
     } else {
         connection.sendSize
             = fread(connection.sendData, 1, FTP_BUFFER_SIZE, fp);
-
         if (FTP_BUFFER_SIZE > connection.sendSize) {
             fclose(fp);
             method = FTP_METHOD_NOOP;
@@ -189,8 +213,7 @@
     DirNorm(tmp);
 
     if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
-        //CHANGE_ET renamed fp to tfp to avoid shadow
-        FILE *tfp = fopen(tmp, "r");
+			FILE *tfp = fopen(tmp, "r"); //CHANGE_ET rename fp to tfp to avoid shadowed variable
         if (tfp != NULL) {
             strncpy(ftpFile, tmp, MAX_STRING_LENGTH);
             fclose(tfp);
@@ -230,6 +253,7 @@
 FtpDTP::List(char* dir)
 {
     char tmp[MAX_STRING_LENGTH * 2];
+    total = true;
 
     if ((dir[0] != '\0') && (dir[0] == '/')) {
         sprintf(tmp, "%s/", dir);
@@ -242,14 +266,23 @@
         listLong = false;
     }
 
+    listLong = true;
 
     DirNorm(tmp);
 
     if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
-        if ((dirp = opendir(tmp))) {
+			if ((dirp = opendir(tmp))) { //CHANGE_ET extra parenthesis to clarify assignment used as truth value
             method = FTP_METHOD_LIST;
             strcpy(ftpFile, tmp);
-            Connect();
+            if (passive) {
+                if (connection.state == CONNECTION_CONNECTED) {
+                    if (!ListSend()) {
+                        Close();
+                    }
+                }
+            } else {
+                Connect();
+            }
             return true;
         }
     }
@@ -262,30 +295,39 @@
     dirent *entry;
     char tmp[MAX_STRING_LENGTH];
 
+    if (total) {
+        sprintf((char *)connection.sendData,
+                "total %d\r\n", 0);
+        connection.sendSize = strlen((char *)connection.sendData);
+        Send();
+        total = false;
+        return true;
+    }
+
     entry = readdir(dirp);
     if (entry) {
         struct stat statbuf;
         sprintf(tmp, "%s/%s", ftpFile, entry->d_name);
         DirNorm(tmp);
         
-        stat(tmp, &statbuf);
+        stat(tmp, &statbuf); //CHANGE_ET unused variable 'ret'
         if (listLong) {
             sprintf((char *)connection.sendData,
-                    "%c%c%c%c%c%c%c%c%c%c %x %s %s %-u %s %d %d %s\r\n",
+                    "%c%c%c%c%c%c%c%c%c%c %x %s %s %-d %s %d %d %s\r\n",
                     (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'd' : '-',
                     (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
                     (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
-                    (statbuf.st_mode & S_IXUSR) ? 'x' : '-',
-                    (statbuf.st_mode & S_IRGRP) ? 'r' : '-',
-                    (statbuf.st_mode & S_IWGRP) ? 'w' : '-',
-                    (statbuf.st_mode & S_IXGRP) ? 'x' : '-',
-                    (statbuf.st_mode & S_IROTH) ? 'r' : '-',
-                    (statbuf.st_mode & S_IWOTH) ? 'w' : '-',
-                    (statbuf.st_mode & S_IXOTH) ? 'x' : '-',
+                    (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
+                    (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
+                    (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
+                    (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
+                    (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
+                    (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
+                    (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
                     0,
                     "AIBO",
                     "AIBO",
-                    (unsigned int)statbuf.st_size,
+                    statbuf.st_size,
                     "May",
                     11,
                     1999,
@@ -328,7 +370,7 @@
 
     if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
         DIR* tmpdirp;
-        if ((tmpdirp = opendir(tmp))) {
+        if ((tmpdirp = opendir(tmp))) { //CHANGE_ET extra parenthesis to clarify assignment used as truth value
             closedir(tmpdirp);
             strcpy(ftpDir, tmp);
             return true;
@@ -344,9 +386,9 @@
     char tmp[MAX_STRING_LENGTH * 2];
 
     if (dir[0] == '/') {
-        sprintf(tmp, "%s/", dir);
+        sprintf(tmp, "%s", dir);
     } else {
-        sprintf(tmp, "%s%s/", ftpDir, dir);
+        sprintf(tmp, "%s%s", ftpDir, dir);
     }
 
     DirNorm(tmp);
@@ -366,9 +408,9 @@
     char tmp[MAX_STRING_LENGTH * 2];
 
     if (dir[0] == '/') {
-        sprintf(tmp, "%s/", dir);
+        sprintf(tmp, "%s", dir);
     } else {
-        sprintf(tmp, "%s%s/", ftpDir, dir);
+        sprintf(tmp, "%s%s", ftpDir, dir);
     }
 
     DirNorm(tmp);
@@ -388,9 +430,9 @@
     char tmp[MAX_STRING_LENGTH * 2];
 
     if (filename[0] == '/') {
-        sprintf(tmp, "%s/", filename);
+        sprintf(tmp, "%s", filename);
     } else {
-        sprintf(tmp, "%s%s/", ftpDir, filename);
+        sprintf(tmp, "%s%s", ftpDir, filename);
     }
 
     DirNorm(tmp);
@@ -407,8 +449,8 @@
 void
 FtpDTP::Save(byte *data, int length, bool end)
 {
-    OSYSDEBUG(("FtpDTP::Save %d\n", length));
-    fwrite(data, length, 1, fp);
+    OSYSDEBUG(("FtpDTP::Save %d %d\n", length, end));
+    if (length) fwrite(data, length, 1, fp);
     if (end) {
         fclose(fp);
         strcpy(ftpFile, "");
@@ -425,8 +467,6 @@
     } else {
         return 0;
     }
-
-    return 0;
 }
 
 void
Index: TinyFTPD/FtpPI.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpPI.cc,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- TinyFTPD/FtpPI.cc	25 Jul 2003 20:18:09 -0000	1.2
+++ TinyFTPD/FtpPI.cc	6 Jul 2004 22:43:45 -0000	1.4
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -14,20 +14,19 @@
 #include <EndpointTypes.h>
 #include <TCPEndpointMsg.h>
 #include "FtpPI.h"
-#include "entry.h"
 
 FtpPI::FtpPI()
 {
 }
 
 OStatus
-FtpPI::Initialize(const OID& myoid, const OID& ipoid,
+FtpPI::Initialize(const OID& myoid, const antStackRef& ipstack,
                   void* index, OList<Passwd, MAX_LOGIN> *pass)
 {
     OSYSDEBUG(("FtpPI::Initialize()\n"));
 
     myOID        = myoid;
-    ipstackOID   = ipoid;
+    ipstackRef   = ipstack;
     continuation = index;
     passwd       = pass;
  
@@ -39,7 +38,7 @@
     //
     antEnvCreateSharedBufferMsg sendBufferMsg(FTP_BUFFER_SIZE);
 
-    sendBufferMsg.Call(ipstackOID, sizeof(sendBufferMsg));
+    sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
     if (sendBufferMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpPI::Initialize()",
@@ -57,7 +56,7 @@
     //
     antEnvCreateSharedBufferMsg recvBufferMsg(FTP_BUFFER_SIZE);
 
-    recvBufferMsg.Call(ipstackOID, sizeof(recvBufferMsg));
+    recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
     if (recvBufferMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpPI::Initialize()",
@@ -70,7 +69,7 @@
     connection.recvBuffer.Map();
     connection.recvData = (byte*)(connection.recvBuffer.GetAddress());
     
-    ftpDTP.Initialize(myOID, ipstackOID, index);
+    ftpDTP.Initialize(myOID, ipstackRef, index);
     Listen();
 
     return oSUCCESS;
@@ -89,7 +88,7 @@
     antEnvCreateEndpointMsg tcpCreateMsg(EndpointType_TCP,
                                          FTP_BUFFER_SIZE * 2);
 
-    tcpCreateMsg.Call(ipstackOID, sizeof(tcpCreateMsg));
+    tcpCreateMsg.Call(ipstackRef, sizeof(tcpCreateMsg));
     if (tcpCreateMsg.error != ANT_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s[%d] antError %d",
                   "FtpPI::Listen()",
@@ -106,7 +105,7 @@
                                    IP_ADDR_ANY, FTP_LISTEN_PORT);
     listenMsg.continuation = continuation;
 
-    listenMsg.Send(ipstackOID, myOID,
+    listenMsg.Send(ipstackRef, myOID,
                    Extra_Entry[entryListenContforPI], sizeof(listenMsg));
     
     connection.state = CONNECTION_LISTENING;
@@ -117,7 +116,11 @@
 void
 FtpPI::ListenCont(TCPEndpointListenMsg* listenMsg)
 {
-    OSYSDEBUG(("FtpPI::ListenCont()\n"));
+    OSYSDEBUG(("FtpPI::ListenCont() %x %d - %x %d\n",
+               listenMsg->lAddress,
+               listenMsg->lPort,
+               listenMsg->fAddress,
+               listenMsg->fPort));
 
     if (listenMsg->error != TCP_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s %d",
@@ -127,6 +130,8 @@
         return;
     }
 
+    ipaddr = listenMsg->lAddress;
+
     connection.state = CONNECTION_CONNECTED;
     Send(FTP_REPLY_SERVICE_READY, "AIBO FTP Server ready");
     connection.recvSize = 0;
@@ -153,7 +158,7 @@
                                strlen((char *)connection.sendData));
     sendMsg.continuation = continuation;
 
-    sendMsg.Send(ipstackOID, myOID,
+    sendMsg.Send(ipstackRef, myOID,
                  Extra_Entry[entrySendContforPI], sizeof(sendMsg));
 
     connection.state = CONNECTION_SENDING;
@@ -190,7 +195,7 @@
                                      1,
                                      FTP_BUFFER_SIZE);
     receiveMsg.continuation = continuation;
-    receiveMsg.Send(ipstackOID, myOID,
+    receiveMsg.Send(ipstackRef, myOID,
                     Extra_Entry[entryReceiveContforPI], sizeof(receiveMsg));
     return oSUCCESS;
 }
@@ -200,6 +205,11 @@
 {
     bool doReceive = false;
 
+    if (receiveMsg->error == TCP_CONNECTION_CLOSED) {
+        Close();
+        return;
+    }
+
     if (receiveMsg->error != TCP_SUCCESS) {
         OSYSLOG1((osyslogERROR, "%s : %s %d",
                   "FtpPI::ReceiveCont()",
@@ -238,7 +248,7 @@
     TCPEndpointCloseMsg closeMsg(connection.endpoint);
     closeMsg.continuation = continuation;
 
-    closeMsg.Send(ipstackOID, myOID,
+    closeMsg.Send(ipstackRef, myOID,
                   Extra_Entry[entryCloseContforPI], sizeof(closeMsg));
 
     connection.state = CONNECTION_CLOSING;
@@ -248,7 +258,7 @@
 }
 
 void
-FtpPI::CloseCont(TCPEndpointCloseMsg* /*closeMsg*/)
+FtpPI::CloseCont(TCPEndpointCloseMsg* /*closeMsg*/) //CHANGE_ET unused variable
 {
     OSYSDEBUG(("FtpPI::CloseCont()\n"));
     
@@ -257,6 +267,28 @@
 }
 
 void
+FtpPI::ListenContforDTP(TCPEndpointListenMsg* listenMsg)
+{
+    if (listenMsg->error == TCP_SUCCESS) {
+        switch(ftpDTP.GetType()) {
+        case FTP_DATA_I:
+            Send(FTP_REPLY_OPEN_CONNECTION,
+                 "Binary data connection for %s.",
+                 ftpDTP.GetFilename());
+            break;
+
+        case FTP_DATA_A:
+            Send(FTP_REPLY_OPEN_CONNECTION,
+                 "ASCII data connection for %s.",
+                 ftpDTP.GetFilename());
+            break;
+        }
+    }
+    ftpDTP.ListenCont(listenMsg);
+    return;
+}
+
+void
 FtpPI::ConnectContforDTP(TCPEndpointConnectMsg* connectMsg)
 {
     if (connectMsg->error == TCP_SUCCESS) {
Index: TinyFTPD/FtpPI.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpPI.h,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- TinyFTPD/FtpPI.h	25 Jul 2003 20:18:09 -0000	1.2
+++ TinyFTPD/FtpPI.h	6 Jul 2004 22:43:45 -0000	1.4
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -17,6 +17,7 @@
 #include "FtpConfig.h"
 #include "FtpDTP.h"
 #include "def.h"
+#include "entry.h"
 
 class FtpPI
 {
@@ -24,7 +25,7 @@
     FtpPI();
     virtual ~FtpPI() {}
 
-    OStatus Initialize(const OID& myoid, const OID& ipoid,
+    OStatus Initialize(const OID& myoid, const antStackRef& ipstack,
                        void* index, OList<Passwd, MAX_LOGIN> *pass);
 
     void ListenCont  (TCPEndpointListenMsg*  listenMsg);
@@ -32,6 +33,7 @@
     void ReceiveCont (TCPEndpointReceiveMsg* receiveMsg);
     void CloseCont   (TCPEndpointCloseMsg*   closeMsg);
 
+    void ListenContforDTP (TCPEndpointListenMsg*  listenMsg);
     void ConnectContforDTP(TCPEndpointConnectMsg* connectMsg);
     void SendContforDTP   (TCPEndpointSendMsg*    sendMsg);
     void ReceiveContforDTP(TCPEndpointReceiveMsg* receiveMsg);
@@ -48,17 +50,18 @@
     bool RequestProcess ();
     bool CommandParser  (char **cmd, char **param);
 
-    OID            myOID;
-    OID            ipstackOID;
+    OID myOID;
+    antStackRef ipstackRef;
     void* continuation;
     TCPConnection connection;
     FTPLoginState state;
     FtpDTP ftpDTP;
+    IPAddress ipaddr;
 
     OList<Passwd, MAX_LOGIN> *passwd;
 
-		FtpPI(const FtpPI&); //!< don't call
-		FtpPI& operator=(const FtpPI&); //!< don't call
+		FtpPI(const FtpPI&); //CHANGE_ET copy constructor, don't call
+		FtpPI operator=(const FtpPI&); //CHANGE_ET assignment operator, don't call
 };
 #endif /* _FtpPI_h_DEFINED */
 
Index: TinyFTPD/FtpRequest.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/FtpRequest.cc,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- TinyFTPD/FtpRequest.cc	30 Sep 2002 18:19:49 -0000	1.1.1.1
+++ TinyFTPD/FtpRequest.cc	6 Jul 2004 22:30:57 -0000	1.2
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -12,7 +12,6 @@
 #include <OPENR/OPENRAPI.h>
 #include <OPENR/OSyslog.h>
 #include "FtpPI.h"
-#include "entry.h"
 
 bool
 FtpPI::RequestComplete()
@@ -130,8 +129,38 @@
         connection.recvSize = 0;
         Receive();
     } else if (!strcmp(cmd, "PORT")) {
-        if (ftpDTP.SetPort(param)) {
-            Send(FTP_REPLY_COMMAND_OK, "PORT command successful.");
+        if (state == FTP_GET_REQUEST) {
+            if (ftpDTP.SetPort(param)) {
+                Send(FTP_REPLY_COMMAND_OK, "PORT command successful.");
+                connection.recvSize = 0;
+                Receive();
+            }
+        } else {
+            Send(FTP_REPLY_NOT_LOGIN, "Please login with USER and PASS.");
+            connection.recvSize = 0;
+            Receive();
+        }
+    } else if (!strcmp(cmd, "PASV")) {
+        if (state == FTP_GET_REQUEST) {
+            Port port = ftpDTP.SetIP(ipaddr);
+            if (port){
+                Send(FTP_REPLY_ENTER_PASSIVE,
+                     "Entering Passive Mode. %d,%d,%d,%d,%d,%d",
+                     (ipaddr.Address() & 0xff000000) >> 24,
+                     (ipaddr.Address() & 0x00ff0000) >> 16,
+                     (ipaddr.Address() & 0x0000ff00) >>  8,
+                     (ipaddr.Address() & 0x000000ff),
+                     (port & 0xff00) >>  8,
+                     (port & 0x00ff));
+                connection.recvSize = 0;
+                Receive();
+            }else {
+                Send(FTP_REPLY_NOT_AVAILABLE, "Passive Mode Fail.");
+                connection.recvSize = 0;
+                Receive();
+            }
+        } else {
+            Send(FTP_REPLY_NOT_LOGIN, "Please login with USER and PASS.");
             connection.recvSize = 0;
             Receive();
         }
@@ -342,13 +371,27 @@
             connection.recvSize = 0;
             Receive();
         }
+    } else if (!strcmp(cmd, "SYST")) {
+        sprintf((char *)connection.sendData,
+                "%03d Aperios system type.\r\n",
+                FTP_REPLY_SYSTEM_TYPE);
+        TCPEndpointSendMsg sendMsg(connection.endpoint,
+                                   connection.sendData,
+                                   strlen((char *)connection.sendData));
+            
+        sendMsg.continuation = continuation;
+        sendMsg.Send(ipstackRef,
+                     myOID, Extra_Entry[entrySendContforPI],
+                     sizeof(TCPEndpointSendMsg));
+        connection.recvSize = 0;
+        Receive();
     } else if (!strcmp(cmd, "HELP")) {
         sprintf((char *)connection.sendData,
                 "%03d-%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%03d %s\r\n",
                 FTP_REPLY_HELP_MESSAGE,
                 "The following commands are recognized:",
                 "   USER    PORT    RETR    MSND*   ALLO*   DELE    SITE*   XMKD*   CDUP",
-                "   PASS    PASV*   STOR    MSOM*   REST*   CWD     STAT*   RMD     XCUP*",
+                "   PASS    PASV    STOR    MSOM*   REST*   CWD     STAT*   RMD     XCUP*",
                 "   ACCT*   TYPE    APPE*   MSAM*   RNFR*   XCWD*   HELP    XRMD*   STOU*",
                 "   REIN*   STRU*   MLFL*   MRSQ*   RNTO*   LIST    NOOP    PWD ",
                 "   QUIT    MODE*   MAIL*   MRCP*   ABOR*   NLST*   MKD     XPWD*   REBT",
@@ -360,14 +403,14 @@
                                    strlen((char *)connection.sendData));
         
         sendMsg.continuation = continuation;
-        sendMsg.Send(ipstackOID,
+        sendMsg.Send(ipstackRef,
                      myOID, Extra_Entry[entrySendContforPI],
                      sizeof(TCPEndpointSendMsg));
         connection.recvSize = 0;
         Receive();
     } else if (!strcmp(cmd, "NOOP")) {
         Send(FTP_REPLY_COMMAND_OK, "NOOP command successful.");
-        Close();
+        Receive();
     } else if (!strcmp(cmd, "QUIT")) {
         Send(FTP_REPLY_SERVICE_CLOSE,
              "Goodbye. Thanks for using the AIBO FTP Server.");
Index: TinyFTPD/TinyFTPD.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/TinyFTPD.cc,v
retrieving revision 1.3
retrieving revision 1.6
diff -u -d -r1.3 -r1.6
--- TinyFTPD/TinyFTPD.cc	25 Jul 2003 20:18:09 -0000	1.3
+++ TinyFTPD/TinyFTPD.cc	6 Jul 2004 23:25:45 -0000	1.6
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -9,7 +9,6 @@
 // implied warranties of fitness for a particular purpose.
 //
 
-#include "TinyFTPD/entry.h"
 #include <sys/stat.h>
 #include <OPENR/OSyslog.h>
 #include <EndpointTypes.h>
@@ -21,32 +20,18 @@
 }
 
 OStatus
-TinyFTPD::DoInit(const OSystemEvent&)
+TinyFTPD::DoInit(const OSystemEvent& /*event*/) //CHANGE_ET unused parameter
 {
     OSYSDEBUG(("TinyFTPD::DoInit()\n"));
     return oSUCCESS;
 }
 
 OStatus
-TinyFTPD::DoStart(const OSystemEvent&)
+TinyFTPD::DoStart(const OSystemEvent& /*event*/) //CHANGE_ET unused parameter
 {
     OSYSDEBUG(("TinyFTPD::DoStart()\n"));
 
-    sError error = WhoAmI(&myOID);
-    if (error != sSUCCESS) {
-        OSYSLOG1((osyslogERROR, "%s : %s %d",
-                  "TinyFTPD::DoStart()",
-                  "WhoAmI() error", error));
-        return oFAIL;
-    }
-
-    error = Find("IPStack", &ipstackOID);
-    if (error != sSUCCESS) {
-        OSYSLOG1((osyslogERROR, "%s : %s %d",
-                  "TinyFTPD::DoStart()",
-                  "Find(IPStack) error", error));
-        return oFAIL;
-    }
+    ipstackRef = antStackRef("IPStack");
 
     // Get Passwd
     OStatus status = LoadPasswd();
@@ -57,14 +42,14 @@
 
     // initialize connection
     for(int index = 0; index < FTP_CONNECTION_MAX; index++) {
-        ftpPI[index].Initialize(myOID, ipstackOID, (void*)index, &passwd);
+        ftpPI[index].Initialize(myOID_, ipstackRef, (void*)index, &passwd);
     }
 
     return oSUCCESS;
 }
 
 OStatus
-TinyFTPD::DoStop(const OSystemEvent&)
+TinyFTPD::DoStop(const OSystemEvent& /*event*/) //CHANGE_ET unused parameter
 {
     OSYSDEBUG(("TinyFTPD::DoStop()\n"));
     for(int index = 0; index < FTP_CONNECTION_MAX; index++) {
@@ -74,79 +59,96 @@
 }
 
 OStatus
-TinyFTPD::DoDestroy(const OSystemEvent&)
+TinyFTPD::DoDestroy(const OSystemEvent& /*event*/) //CHANGE_ET unused parameter
 {
     OSYSDEBUG(("TinyFTPD::DoDestroy()\n"));
     return oSUCCESS;
 }
 
 void
-TinyFTPD::ListenContforPI(void* msg)
+TinyFTPD::ListenContforPI(ANTENVMSG msg)
 {
-    TCPEndpointListenMsg* listenMsg = (TCPEndpointListenMsg*)msg;
+    TCPEndpointListenMsg* listenMsg
+        = (TCPEndpointListenMsg*)antEnvMsg::Receive(msg);
     int index = (int)(listenMsg->continuation);
 
     ftpPI[index].ListenCont(listenMsg);
 }
 
 void
-TinyFTPD::SendContforPI(void* msg)
+TinyFTPD::SendContforPI(ANTENVMSG msg)
 {
-    TCPEndpointSendMsg* sendMsg = (TCPEndpointSendMsg*)msg;
+    TCPEndpointSendMsg* sendMsg = (TCPEndpointSendMsg*)antEnvMsg::Receive(msg);
     int index = (int)(sendMsg->continuation);
 
     ftpPI[index].SendCont(sendMsg);
 }
 
 void
-TinyFTPD::ReceiveContforPI(void* msg)
+TinyFTPD::ReceiveContforPI(ANTENVMSG msg)
 {
-    TCPEndpointReceiveMsg* receiveMsg = (TCPEndpointReceiveMsg*)msg;
+    TCPEndpointReceiveMsg* receiveMsg
+        = (TCPEndpointReceiveMsg*)antEnvMsg::Receive(msg);
     int index = (int)(receiveMsg->continuation);
 
     ftpPI[index].ReceiveCont(receiveMsg);
 }
 
 void
-TinyFTPD::CloseContforPI(void* msg)
+TinyFTPD::CloseContforPI(ANTENVMSG msg)
 {
-    TCPEndpointCloseMsg* closeMsg = (TCPEndpointCloseMsg*)msg;
+    TCPEndpointCloseMsg* closeMsg
+        = (TCPEndpointCloseMsg*)antEnvMsg::Receive(msg);
     int index = (int)(closeMsg->continuation);
    
     ftpPI[index].CloseCont(closeMsg);
 }
 
 void
-TinyFTPD::ConnectContforDTP(void* msg)
+TinyFTPD::ListenContforDTP(ANTENVMSG msg)
 {
-    TCPEndpointConnectMsg* connectMsg = (TCPEndpointConnectMsg*)msg;
+    TCPEndpointListenMsg* listenMsg
+        = (TCPEndpointListenMsg*)antEnvMsg::Receive(msg);
+    int index = (int)(listenMsg->continuation);
+
+    ftpPI[index].ListenContforDTP(listenMsg);
+}
+
+void
+TinyFTPD::ConnectContforDTP(ANTENVMSG msg)
+{
+    TCPEndpointConnectMsg* connectMsg
+        = (TCPEndpointConnectMsg*)antEnvMsg::Receive(msg);
     int index = (int)(connectMsg->continuation);
 
     ftpPI[index].ConnectContforDTP(connectMsg);
 }
 
 void
-TinyFTPD::SendContforDTP(void* msg)
+TinyFTPD::SendContforDTP(ANTENVMSG msg)
 {
-    TCPEndpointSendMsg* sendMsg = (TCPEndpointSendMsg*)msg;
+    TCPEndpointSendMsg* sendMsg
+        = (TCPEndpointSendMsg*)antEnvMsg::Receive(msg);
     int index = (int)(sendMsg->continuation);
 
     ftpPI[index].SendContforDTP(sendMsg);
 }
 
 void
-TinyFTPD::ReceiveContforDTP(void* msg)
+TinyFTPD::ReceiveContforDTP(ANTENVMSG msg)
 {
-    TCPEndpointReceiveMsg* receiveMsg = (TCPEndpointReceiveMsg*)msg;
+    TCPEndpointReceiveMsg* receiveMsg
+        = (TCPEndpointReceiveMsg*)antEnvMsg::Receive(msg);
     int index = (int)(receiveMsg->continuation);
 
     ftpPI[index].ReceiveContforDTP(receiveMsg);
 }
 
 void
-TinyFTPD::CloseContforDTP(void* msg)
+TinyFTPD::CloseContforDTP(ANTENVMSG msg)
 {
-    TCPEndpointCloseMsg* closeMsg = (TCPEndpointCloseMsg*)msg;
+    TCPEndpointCloseMsg* closeMsg
+        = (TCPEndpointCloseMsg*)antEnvMsg::Receive(msg);
     int index = (int)(closeMsg->continuation);
 
     ftpPI[index].CloseContforDTP(closeMsg);
@@ -171,6 +173,13 @@
     Passwd pass;
 
     while (cur < end) {
+        if(*cur=='#') { // CHANGE_ET lets us put commented lines in the passwd file
+					while(*cur!='\n' && *cur!='\r' && cur<end)
+						cur++;
+					while((*cur=='\n' || *cur=='\r') && cur<end)
+						cur++;
+					continue;
+				}
         while (isspace(*cur)) cur++;
         head = cur;
         while (!isspace(*cur) && (cur < end)) cur++;
@@ -192,8 +201,7 @@
         *cur++ = '\0';
         strcpy(pass.home, head);
 
-				if(pass.user[0]!='#') // CHANGE_ET lets us put commented lines in the passwd file
-					if (passwd.PushBack(pass)) break;
+        if (passwd.PushBack(pass)) break;
     }
 
     DeleteRegion(buf);
@@ -203,7 +211,6 @@
 OStatus
 TinyFTPD::Load(char* path, byte** data, size_t* size)
 {
-    struct stat statbuf;
     FILE* fp;
     byte* readBuf = 0;
     int readBufSize;
@@ -211,10 +218,12 @@
     *data = 0;
     *size = 0;
 
+    struct stat statbuf;
     int ret = stat(path, &statbuf);
     if (ret != 0) return oNOT_FOUND;
 
     readBufSize = statbuf.st_size;
+
     OSYSDEBUG(("%s size %d readBufSize %d\n",
                path, statbuf.st_size, readBufSize));
 
@@ -234,7 +243,7 @@
         free(readBuf);
         return oFAIL;
     }
-
+    
 	*data = readBuf;
 	*size = statbuf.st_size;
 
Index: TinyFTPD/TinyFTPD.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/TinyFTPD.h,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -d -r1.2 -r1.4
--- TinyFTPD/TinyFTPD.h	25 Jul 2003 20:18:09 -0000	1.2
+++ TinyFTPD/TinyFTPD.h	6 Jul 2004 22:43:45 -0000	1.4
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -34,27 +34,27 @@
     virtual OStatus DoStop   (const OSystemEvent& event);
     virtual OStatus DoDestroy(const OSystemEvent& event);
 
-    void ListenContforPI  (void* msg);
-    void SendContforPI    (void* msg);
-    void ReceiveContforPI (void* msg);
-    void CloseContforPI   (void* msg);
-    void ConnectContforDTP(void* msg);
-    void SendContforDTP   (void* msg);
-    void ReceiveContforDTP(void* msg);
-    void CloseContforDTP  (void* msg);
+    void ListenContforPI  (ANTENVMSG msg);
+    void SendContforPI    (ANTENVMSG msg);
+    void ReceiveContforPI (ANTENVMSG msg);
+    void CloseContforPI   (ANTENVMSG msg);
+    void ListenContforDTP (ANTENVMSG msg);
+    void ConnectContforDTP(ANTENVMSG msg);
+    void SendContforDTP   (ANTENVMSG msg);
+    void ReceiveContforDTP(ANTENVMSG msg);
+    void CloseContforDTP  (ANTENVMSG msg);
 
 private:
     OStatus LoadPasswd();
     OStatus Load(char* path, byte** data, size_t* size);
 
-    OID            myOID;
-    OID            ipstackOID;
+    antStackRef ipstackRef;
     FtpPI ftpPI[FTP_CONNECTION_MAX];
 
     OList<Passwd, MAX_LOGIN> passwd;
 
-		TinyFTPD(const TinyFTPD&); //!< don't call
-		TinyFTPD& operator=(const TinyFTPD&); //!< don't call
+		TinyFTPD(const TinyFTPD&); //CHANGE_ET copy constructor, don't call
+		TinyFTPD operator=(const TinyFTPD&); //CHANGE_ET assignment operator, don't call
 };
-#endif /* _TinyFTPD_h_DEFINED */
 
+#endif /* _TinyFTPD_h_DEFINED */
Index: TinyFTPD/stub.cfg
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/TinyFTPD/stub.cfg,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- TinyFTPD/stub.cfg	30 Sep 2002 18:19:49 -0000	1.1.1.1
+++ TinyFTPD/stub.cfg	6 Jul 2004 22:30:57 -0000	1.2
@@ -1,5 +1,5 @@
 //
-// Copyright 2002 Sony Corporation 
+// Copyright 2002,2003 Sony Corporation 
 //
 // Permission to use, copy, modify, and redistribute this software for
 // non-commercial use is hereby granted.
@@ -19,6 +19,7 @@
 Extra : SendContforPI()
 Extra : ReceiveContforPI()
 Extra : CloseContforPI()
+Extra : ListenContforDTP()
 Extra : ConnectContforDTP()
 Extra : SendContforDTP()
 Extra : ReceiveContforDTP()
Index: Vision/SegmentedColorGenerator.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Vision/SegmentedColorGenerator.h,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- Vision/SegmentedColorGenerator.h	18 Feb 2004 21:13:32 -0000	1.6
+++ Vision/SegmentedColorGenerator.h	17 Jul 2004 03:29:24 -0000	1.9
@@ -4,6 +4,7 @@
 
 #include "Vision/FilterBankGenerator.h"
 #include "Vision/cmvision.h"
+#include "Vision/colors.h"
 #include <ext/hash_map>
 #include <vector>
 
@@ -91,7 +92,31 @@
 	
 	//! returns index of color corresponding to a string (uses a fast hash lookup)
 	unsigned int getColorIndex(const std::string& name) const { return getColorIndex(name.c_str()); }
-	
+
+	unsigned int getColorIndex(const rgb color) const {
+		for(unsigned int index = 0; index < getNumColors(); index++)
+			if(getColorRGB((int)index) == color)
+				return index;
+		return 0;
+	}
+
+
+	//! returns rgb struct (from colors.h) correspondingto an int index.
+	rgb getColorRGB(const int index) const {
+		return(getColors()[index].color);
+	}
+
+	//! returns rgb struct (from colors.h) corresponding to a string.
+	rgb getColorRGB(const char * name) const {
+		return(getColorRGB(getColorIndex(name)));
+	}
+
+	//! returns rgb struct (from colors.h) corresponding to a string.
+	rgb getColorRGB(const std::string& name) const { 
+		return getColorRGB(name.c_str()); 
+	}
+
+
 	virtual unsigned int getBinSize() const;
 	virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
 	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
@@ -135,11 +160,11 @@
  * @author alokl (Creator)
  * @author ejt (reorganized)
  *
- * $Author: ejt $
+ * $Author: wales $
  * $Name:  $
- * $Revision: 1.6 $
+ * $Revision: 1.9 $
  * $State: Exp $
- * $Date: 2004/02/18 21:13:32 $
+ * $Date: 2004/07/17 03:29:24 $
  */
 
 #endif
Index: Vision/cmv_types.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Vision/cmv_types.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Vision/cmv_types.h	23 Jan 2003 18:14:11 -0000	1.2
+++ Vision/cmv_types.h	16 Jul 2004 22:27:59 -0000	1.3
@@ -110,6 +110,9 @@
 };
 
 struct color_class_state{
+	color_class_state() : list(), num(), min_area(), total_area(), merge_threshold(), color(), name() {}
+	color_class_state(const color_class_state& c) : list(c.list), num(c.num), min_area(c.min_area), total_area(c.total_area), merge_threshold(c.merge_threshold), color(c.color), name(c.name) {}
+	color_class_state operator=(const color_class_state& c) { list=c.list; num=c.num; min_area=c.min_area; total_area=c.total_area; merge_threshold=c.merge_threshold; color=c.color; name=c.name; return *this;}
   region *list;          // head of region list for this color
   int num;               // number of regions of this color
   int min_area;          // minimum area for a meaningful region
Index: Vision/colors.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Vision/colors.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Vision/colors.h	1 Mar 2003 20:53:42 -0000	1.3
+++ Vision/colors.h	16 Jul 2004 22:11:38 -0000	1.4
@@ -66,11 +66,18 @@
 #define RGB_STRUCT
 struct rgb{
   uchar red,green,blue;
+
+	rgb(int r=0, int g=0, int b=0)
+		: red((uchar)r), green((uchar)g), blue((uchar)b)
+	{ };
+			 
+
   bool operator ==(const rgb &x) const {
     return (red  ==x.red   &&
             green==x.green &&
             blue ==x.blue);
   }
+
   bool operator !=(const rgb &x) const {
     return !operator==(x);
   }
@@ -123,17 +130,29 @@
 
 #ifdef RGB_COLOR_NAMES
 namespace Rgb{
-  const rgb Black   = {  0,  0,  0};
-  const rgb Blue    = {  0,128,255};
-  const rgb Green   = {  0,128,  0};
-  const rgb Orange  = {255,128,  0};
-  const rgb Bgreen  = {  0,255,  0};
-  const rgb Purple  = {128,  0,255};
-  const rgb Red     = {255,  0,  0};
-  const rgb Pink    = {255,128,224};
-  const rgb Yellow  = {255,255,  0};
-  const rgb Gray    = {200,200,200};
-  const rgb Skin    = {150,100,  0};
+/*   const rgb Black   = {  0,  0,  0}; */
+/*   const rgb Blue    = {  0,128,255}; */
+/*   const rgb Green   = {  0,128,  0}; */
+/*   const rgb Orange  = {255,128,  0}; */
+/*   const rgb Bgreen  = {  0,255,  0}; */
+/*   const rgb Purple  = {128,  0,255}; */
+/*   const rgb Red     = {255,  0,  0}; */
+/*   const rgb Pink    = {255,128,224}; */
+/*   const rgb Yellow  = {255,255,  0}; */
+/*   const rgb Gray    = {200,200,200}; */
+/*   const rgb Skin    = {150,100,  0}; */
+
+/*   const rgb Black(0,  0,  0); */
+/*   const rgb Blue(0,128,255); */
+/*   const rgb Green(  0,128,  0); */
+/*   const rgb Orange(255,128,  0); */
+/*   const rgb Bgreen(0,255,  0); */
+/*   const rgb Purple(128,  0,255); */
+/*   const rgb Red(255,  0,  0); */
+/*   const rgb Pink(255,128,224); */
+/*   const rgb Yellow(255,255,  0); */
+/*   const rgb Gray(200,200,200); */
+/*   const rgb Skin(150,100,  0); */
 }
 #endif
 
Index: Wireless/Socket.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Wireless/Socket.cc,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- Wireless/Socket.cc	14 Jan 2004 20:45:41 -0000	1.16
+++ Wireless/Socket.cc	4 Oct 2004 20:38:05 -0000	1.17
@@ -1,6 +1,8 @@
 #include "Socket.h"
 #include <stdio.h>
-#include "Wireless.h"
+#ifdef PLATFORM_APERIOS
+#  include "Wireless.h"
+#endif
 #include "Shared/Config.h"
 #include <unistd.h>
 
@@ -77,12 +79,16 @@
 				writeData=tempData;
 				sendSize=writeSize;
 				writeSize=tempSize;
-				wireless->send(sock); 
+#ifdef PLATFORM_APERIOS
+				wireless->send(sock);
+#endif
 			}
 		} else {
 			sendData=writeData;
 			sendSize=writeSize;
+#ifdef PLATFORM_APERIOS
 			wireless->blockingSend(sock);
+#endif
 			writeSize=0;
 		}
 	}
@@ -167,8 +173,8 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.16 $
+ * $Revision: 1.17 $
  * $State: Exp $
- * $Date: 2004/01/14 20:45:41 $
+ * $Date: 2004/10/04 20:38:05 $
  */
 
Index: Wireless/Socket.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Wireless/Socket.h,v
retrieving revision 1.16
retrieving revision 1.18
diff -u -d -r1.16 -r1.18
--- Wireless/Socket.h	11 Dec 2003 05:49:31 -0000	1.16
+++ Wireless/Socket.h	4 Oct 2004 20:38:05 -0000	1.18
@@ -1,9 +1,12 @@
 #ifndef Socket_h_DEFINED
 #define Socket_h_DEFINED
 
-#include <ant.h>
-#include <Types.h>
+#ifdef PLATFORM_APERIOS
+#  include <ant.h>
+#  include <Types.h>
+#endif
 #include <stdarg.h>
+#include <stdlib.h>
 
 namespace SocketNS {
   //! Specifies transport type. TCP is usually a good idea
@@ -32,7 +35,9 @@
 
 using namespace SocketNS;
 
-class Wireless;
+#ifndef PLATFORM_APERIOS
+  typedef unsigned char byte;
+#endif
 
 //! Tekkotsu wireless Socket class
 /*! 
@@ -42,6 +47,13 @@
  * - <a href="../RemoteProcess.html">Remote Processing OPENR</a>
  * Tekkotsu Wireless and Remote Processing OPENR provide different
  * interfaces to comparable wireless functionality.
+ *
+ * The networking interface needs more documentation.  It also needs a
+ * cleanup.  In the mean time, take a look at the TekkotsuMon objects
+ * in <i>Tekkotsu</i><tt>/Behaviors/Mon</tt>.  They all listen for new
+ * connections.  Unfortunately, at the momement there are no examples
+ * of outgoing connections, but it should give you a pretty good idea
+ * how to start moving.
  */
 
 class Socket {
@@ -179,6 +191,11 @@
 
   int verbosity;
 
+#ifndef PLATFORM_APERIOS
+  typedef char* antSharedBuffer;
+  typedef unsigned int antModuleRef;
+#endif
+
   antModuleRef endpoint;
   ConnectionState state;
 
@@ -212,9 +229,9 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.16 $
+ * $Revision: 1.18 $
  * $State: Exp $
- * $Date: 2003/12/11 05:49:31 $
+ * $Date: 2004/10/04 20:38:05 $
  */
 
 #endif
Index: Wireless/Wireless.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Wireless/Wireless.cc,v
retrieving revision 1.16
retrieving revision 1.19
diff -u -d -r1.16 -r1.19
--- Wireless/Wireless.cc	11 Dec 2003 05:49:31 -0000	1.16
+++ Wireless/Wireless.cc	28 Sep 2004 22:12:35 -0000	1.19
@@ -1,11 +1,10 @@
-
 #include <OPENR/OSyslog.h>
 #include <OPENR/OPENRAPI.h>
 #include <ant.h>
 #include <EndpointTypes.h>
 #include <TCPEndpointMsg.h>
 #include <UDPEndpointMsg.h>
-#include <string.h>
+#include <cstring>
 #include "Wireless.h"
 #include "Socket.h"
 #include "MMCombo/entry.h"
@@ -15,370 +14,490 @@
 Wireless *wireless=NULL;
 
 Wireless::Wireless ()
-  : ipstackRef(), myOID(), freeSockets()
+	: ipstackRef(), myOID(), freeSockets()
 {
-  ipstackRef = antStackRef("IPStack");
-  WhoAmI(&myOID);
+	ipstackRef = antStackRef("IPStack");
+	WhoAmI(&myOID);
 
-  sockets[0]=new DummySocket(0);
-  for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
-    sockets[sock]=NULL;
-    freeSockets.push_back(sock);
-  }
+	sockets[0]=new DummySocket(0);
+	for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
+		sockets[sock]=NULL;
+		freeSockets.push_back(sock);
+	}
 }    
 
 Wireless::~Wireless ()
 {
-  // TODO
+	// TODO
 }
 
 Socket* Wireless::socket(TransportType_t ttype)
 {
-  return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
+	return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
 }
 
 Socket* Wireless::socket(TransportType_t ttype, int recvsize, int sendsize)
 {
-  if (freeSockets.empty()
-      || (recvsize + sendsize) <= 256) return sockets[0];
-  int sock_num=freeSockets.front();
-  freeSockets.pop_front();
+	if (freeSockets.empty()
+			|| (recvsize + sendsize) <= 256) return sockets[0];
+	int sock_num=freeSockets.front();
+	freeSockets.pop_front();
 
-  sockets[sock_num]=new Socket(sock_num);
-  sockets[sock_num]->trType=ttype;
-  sockets[sock_num]->sendBufSize=sendsize;
-  sockets[sock_num]->recvBufSize=recvsize;
+	sockets[sock_num]=new Socket(sock_num);
+	sockets[sock_num]->trType=ttype;
+	sockets[sock_num]->sendBufSize=sendsize;
+	sockets[sock_num]->recvBufSize=recvsize;
 
-  // setup send buffer
-  antEnvCreateSharedBufferMsg sendBufferMsg(sendsize*2);
-  sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
-  if (sendBufferMsg.error != ANT_SUCCESS) return sockets[0];
-  
-  sockets[sock_num]->sendBuffer = sendBufferMsg.buffer;
-  sockets[sock_num]->sendBuffer.Map();
-  sockets[sock_num]->sendData
-        = (byte*)(sockets[sock_num]->sendBuffer.GetAddress());
+	// setup send buffer
+	antEnvCreateSharedBufferMsg sendBufferMsg(sendsize*2);
+	sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
+	if (sendBufferMsg.error != ANT_SUCCESS) return sockets[0];
 
-  // setup receive buffer
-  antEnvCreateSharedBufferMsg recvBufferMsg(recvsize*2);
-  recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
-  if (recvBufferMsg.error != ANT_SUCCESS) return sockets[0];
-  
-  sockets[sock_num]->recvBuffer = recvBufferMsg.buffer;
-  sockets[sock_num]->recvBuffer.Map();
-  sockets[sock_num]->recvData
-        = (byte*)(sockets[sock_num]->recvBuffer.GetAddress());
+	sockets[sock_num]->sendBuffer = sendBufferMsg.buffer;
+	sockets[sock_num]->sendBuffer.Map();
+	sockets[sock_num]->sendData = ( byte * ) ( sockets[sock_num]->sendBuffer.GetAddress() );
 
-  sockets[sock_num]->readData=sockets[sock_num]->recvData+recvsize;
-  sockets[sock_num]->writeData=sockets[sock_num]->sendData+sendsize;
+	// setup receive buffer
+	antEnvCreateSharedBufferMsg recvBufferMsg(recvsize*2);
+	recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
+	if (recvBufferMsg.error != ANT_SUCCESS) return sockets[0];
 
-  return sockets[sock_num]; 
+	sockets[sock_num]->recvBuffer = recvBufferMsg.buffer;
+	sockets[sock_num]->recvBuffer.Map();
+	sockets[sock_num]->recvData = ( byte * ) ( sockets[sock_num]->recvBuffer.GetAddress() );
+
+	sockets[sock_num]->readData = sockets[sock_num]->recvData + recvsize;
+	sockets[sock_num]->writeData = sockets[sock_num]->sendData + sendsize;
+
+	return sockets[sock_num]; 
 }
 
 int Wireless::listen(int sock, int port)
 {
-  if (port<=0 || port>=65535
-      || sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CLOSED) return -1;
-  
-  sockets[sock]->server_port=port;
-  sockets[sock]->init();
+	if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
+			 || sockets[sock]->state != CONNECTION_CLOSED )return -1;
 
-  if (sockets[sock]->trType==SOCK_STREAM) {
-    // create endpoint
-    antEnvCreateEndpointMsg tcpCreateMsg(EndpointType_TCP,
-                                         (sockets[sock]->recvBufSize+
-                                         sockets[sock]->sendBufSize)*3);
-    tcpCreateMsg.Call(ipstackRef, sizeof(tcpCreateMsg));
-    if (tcpCreateMsg.error != ANT_SUCCESS) return -1;
-    sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
+	sockets[sock]->server_port = port;
+	sockets[sock]->init();
 
-    // listen
-    TCPEndpointListenMsg listenMsg(sockets[sock]->endpoint,
-                                   IP_ADDR_ANY, port);
-    listenMsg.continuation = (void*)sock;
+	if (sockets[sock]->trType==SOCK_STREAM) {
+		// create endpoint
+		antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
+		tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
+		if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
+		sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
 
-    listenMsg.Send(ipstackRef, myOID,
-                   Extra_Entry[entryListenCont], sizeof(listenMsg));
-    
-    sockets[sock]->state = CONNECTION_LISTENING;
-    return 0;
-  } else if (sockets[sock]->trType==SOCK_DGRAM) {
-    // create endpoint
-    antEnvCreateEndpointMsg udpCreateMsg(EndpointType_UDP,
-                                         (sockets[sock]->recvBufSize+
-                                         sockets[sock]->sendBufSize)*3);
-    udpCreateMsg.Call(ipstackRef, sizeof(udpCreateMsg));
-    if (udpCreateMsg.error != ANT_SUCCESS) return -1;
-    sockets[sock]->endpoint = udpCreateMsg.moduleRef;
+		// listen
+		TCPEndpointListenMsg listenMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
+		listenMsg.continuation = ( void * ) sock;
 
-    // bind
-    UDPEndpointBindMsg bindMsg(sockets[sock]->endpoint,
-                                   IP_ADDR_ANY, port);
-    bindMsg.continuation = (void*)sock;
+		listenMsg.Send( ipstackRef, myOID, Extra_Entry[entryListenCont], sizeof( listenMsg ) );
 
-    bindMsg.Send(ipstackRef, myOID,
-                 Extra_Entry[entryBindCont], sizeof(bindMsg));
-    
-    sockets[sock]->state = CONNECTION_LISTENING;
-    return 0;
-  } else {
-    return -1;
-  }
+		sockets[sock]->state = CONNECTION_LISTENING;
+		return 0;
+	} else if (sockets[sock]->trType==SOCK_DGRAM) {
+		// create endpoint
+		antEnvCreateEndpointMsg udpCreateMsg( EndpointType_UDP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
+		udpCreateMsg.Call( ipstackRef, sizeof( udpCreateMsg ) );
+		if ( udpCreateMsg.error != ANT_SUCCESS ) return -1;
+
+		// bind socket
+		sockets[sock]->endpoint = udpCreateMsg.moduleRef;
+		UDPEndpointBindMsg bindMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
+		bindMsg.Call( ipstackRef, sizeof( bindMsg ) );
+		bindMsg.continuation = ( void * ) sock;
+
+		sockets[sock]->state = CONNECTION_CONNECTING;
+
+		receive( sock );
+
+		return 0;
+
+	}
+
+	else
+		return -1;
 }
 
-int Wireless::connect(int sock, const char* ipaddr, int port)
+/** Tell the ipstack we want to recieve messages with this function. */
+
+int Wireless::connect( int sock, const char * ipaddr, int port )
 {
-  if (port<=0 || port>=65535
-      || sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CLOSED) return -1;
-  
-  sockets[sock]->init();
-  if (sockets[sock]->trType==SOCK_STREAM) {
-    // create endpoint
-    antEnvCreateEndpointMsg tcpCreateMsg(EndpointType_TCP,
-                                         (sockets[sock]->recvBufSize+
-                                         sockets[sock]->sendBufSize)*3);
-    tcpCreateMsg.Call(ipstackRef, sizeof(tcpCreateMsg));
-    if (tcpCreateMsg.error != ANT_SUCCESS) return -1;
-    sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
+	if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
+			 || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CLOSED ) ) return -1;
 
-    // connect
-    TCPEndpointConnectMsg connectMsg(sockets[sock]->endpoint,
-                                    IP_ADDR_ANY, IP_PORT_ANY, ipaddr, port);
-    connectMsg.continuation = (void*)sock;
+	sockets[sock]->init();
+	if (sockets[sock]->trType==SOCK_STREAM) {
+		// create endpoint
+		antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
+		tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
+		if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
+		sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
 
-    connectMsg.Send(ipstackRef, myOID,
-                    Extra_Entry[entryConnectCont], sizeof(connectMsg));
-    
-    sockets[sock]->state = CONNECTION_CONNECTING;
-    return 0;
-  } else if (sockets[sock]->trType==SOCK_DGRAM) {
-    //TODO
-    return 0;
-  } else {
-    return -1;
-  }
+		// connect
+		TCPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, IP_ADDR_ANY, IP_PORT_ANY, ipaddr, port );
+		connectMsg.continuation = ( void * ) sock;
+
+		connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
+
+		sockets[sock]->state = CONNECTION_CONNECTING;
+		return 0;
+	}
+
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			// connect
+			UDPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, ipaddr, port );
+
+			connectMsg.continuation = ( void * ) sock;
+
+			connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
+
+			sockets[sock]->state = CONNECTION_CONNECTED;
+			//std::cout << "Sock " << sock << " connected via UDP to IP " << ipaddr << " port " << port << std::flush << std::endl;
+
+			return 0;
+		}
+
+	else
+		{
+			return -1;
+		}
 }
 
 void
 Wireless::ListenCont(void* msg)
 {
-  TCPEndpointListenMsg* listenMsg = (TCPEndpointListenMsg*)msg;
-  int sock = (int)listenMsg->continuation;
+	antEnvMsg * Msg = ( antEnvMsg * ) msg;
+	int sock = ( int )( Msg->continuation );
 
-  if (listenMsg->error != TCP_SUCCESS) {
-    sockets[sock]->state = CONNECTION_ERROR;
-    // no use recycling since its a resource issue
-    return;
-  }
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointListenMsg * listenMsg = ( TCPEndpointListenMsg * ) msg;
 
-  sockets[sock]->state = CONNECTION_CONNECTED;
-  if (sockets[sock]->rcvcbckfn) { receive(sock); }
+			if ( listenMsg->error != TCP_SUCCESS )
+				{
+					sockets[sock]->state = CONNECTION_ERROR;
+
+					// no use recycling since its a resource issue
+					return;
+				}
+
+			sockets[sock]->state = CONNECTION_CONNECTED;
+			receive( sock );
+		}
 }
 
 void
 Wireless::ConnectCont(void *msg)
 {
-  TCPEndpointConnectMsg* connectMsg = (TCPEndpointConnectMsg*)msg;
-  int sock = (int)connectMsg->continuation;
+	antEnvMsg * Msg = ( antEnvMsg * ) msg;
+	int sock = ( int )( Msg->continuation );
 
-  if (connectMsg->error != TCP_SUCCESS) {
-    sockets[sock]->state = CONNECTION_ERROR;
-    return;
-  }
-  
-  sockets[sock]->state = CONNECTION_CONNECTED;
-  if (sockets[sock]->rcvcbckfn) { receive(sock); }  //Thanks to Andrew Cristina <acristin@cs.uno.edu>, et. al. for bug fix
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointConnectMsg * connectMsg = ( TCPEndpointConnectMsg * ) msg;
+			if ( connectMsg->error != TCP_SUCCESS )
+				{
+					sockets[sock]->state = CONNECTION_ERROR;
+					return;
+				}
+
+			sockets[sock]->state = CONNECTION_CONNECTED;
+			receive( sock );
+		}
 }
 
 void
 Wireless::BindCont(void *msg)
 {
-  UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*)msg;
-  int sock = (int)bindMsg->continuation;
+	UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*)msg;
+	int sock = (int)bindMsg->continuation;
 
-  if (bindMsg->error != UDP_SUCCESS) {
-    sockets[sock]->state = CONNECTION_ERROR;
-    return;
-  }
+	if (bindMsg->error != UDP_SUCCESS) {
+		sockets[sock]->state = CONNECTION_ERROR;
+		return;
+	}
 
-  sockets[sock]->state = CONNECTION_CONNECTED;
+	sockets[sock]->state = CONNECTION_CONNECTED;
 }
 
 void
 Wireless::send(int sock)
 {
-  if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CONNECTED
-      || sockets[sock]->sendSize <= 0) return;
+	if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
+			 || sockets[sock]->sendSize <= 0 ) return;
 
-    TCPEndpointSendMsg sendMsg(sockets[sock]->endpoint,
-                               sockets[sock]->sendData,
-                               sockets[sock]->sendSize);
-    sendMsg.continuation = (void*)sock;
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
+			sendMsg.continuation = ( void * ) sock;
 
-    sockets[sock]->tx=true;
-    sendMsg.Send(ipstackRef, myOID,
-                 Extra_Entry[entrySendCont],
-                 sizeof(TCPEndpointSendMsg));
-    sockets[sock]->sendSize = 0;
+			sockets[sock]->tx = true;
+			sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( TCPEndpointSendMsg ) );
+			sockets[sock]->sendSize = 0;
+		}
+
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
+
+			// this field is just hijacked to id the socket # this message is being sent across
+			sendMsg.continuation = ( void * ) sock;
+
+			sockets[sock]->tx = true;
+			sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( UDPEndpointSendMsg ) );
+			sockets[sock]->sendSize = 0;
+		}
 }
 
 void
 Wireless::SendCont(void* msg)
 {
-    TCPEndpointSendMsg* sendMsg = (TCPEndpointSendMsg*)msg;
-    int sock = (int)(sendMsg->continuation);
+	antEnvMsg * Msg = ( antEnvMsg * ) msg;
+	int sock = ( int )( Msg->continuation );
 
-    sockets[sock]->tx=false;
-    if (sendMsg->error != TCP_SUCCESS) {
-      sockets[sock]->state=CONNECTION_ERROR;
-      close(sock);
-      return;
-    }
-    sockets[sock]->flush();
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointSendMsg * sendMsg = ( TCPEndpointSendMsg * ) msg;
+			sockets[sock]->tx = false;
+			if ( sendMsg->error != TCP_SUCCESS )
+				{
+					sockets[sock]->state = CONNECTION_ERROR;
+					close( sock );
+					return;
+				}
+		}
+
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointSendMsg * sendMsg = ( UDPEndpointSendMsg * ) msg;
+			sockets[sock]->tx = false;
+			if ( sendMsg->error != UDP_SUCCESS )
+				{
+					sockets[sock]->state = CONNECTION_ERROR;
+					close( sock );
+					return;
+				}
+		}
+
+	sockets[sock]->flush();
 }
 
 /*! @bug This doesn't actually seem to block until the message is
- *	fully sent... a crash immediately after this will still cause a
- *	line or two to be dropped.  This is still less dropped than
- *	regular send, but doesn't do much good for debugging until we fix
- *	this. (if we can...) */
+*	fully sent... a crash immediately after this will still cause a
+*	line or two to be dropped.  This is still less dropped than
+*	regular send, but doesn't do much good for debugging until we fix
+*	this. (if we can...) */
 void
 Wireless::blockingSend(int sock)
 {
-  if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CONNECTED
-      || sockets[sock]->sendSize <= 0) return;
+	if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
+			 || sockets[sock]->sendSize <= 0 ) return;
 
-    TCPEndpointSendMsg sendMsg(sockets[sock]->endpoint,
-                               sockets[sock]->sendData,
-                               sockets[sock]->sendSize);
-    sendMsg.continuation = (void*)sock;
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
+			sendMsg.continuation = ( void * ) sock;
 
-    sockets[sock]->tx=true;
-    sockets[sock]->sendSize = 0;
-    sendMsg.Call(ipstackRef, sizeof(TCPEndpointSendMsg));
-    sockets[sock]->tx=false;
-    // no double buffering
+			sockets[sock]->tx=true;
+			sockets[sock]->sendSize = 0;
+			sendMsg.Call( ipstackRef, sizeof( TCPEndpointSendMsg ) );
+			sockets[sock]->tx = false;
+		}
+
+	// no double buffering
 }
 
 void
 Wireless::setReceiver(int sock, int (*rcvcbckfn) (char*, int) )
 {
-  if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL) return;
+	if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL) return;
 
-  sockets[sock]->rcvcbckfn=rcvcbckfn;
+	sockets[sock]->rcvcbckfn=rcvcbckfn;
 }
 
 void
 Wireless::receive(int sock)
 {
-  if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CONNECTED) return;
-  
-  TCPEndpointReceiveMsg receiveMsg(sockets[sock]->endpoint,
-                                   sockets[sock]->recvData,
-                                   1,sockets[sock]->recvBufSize);
-  receiveMsg.continuation = (void*)sock;
+	if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
+			 || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CONNECTED ) )
+		return;
 
-  receiveMsg.Send(ipstackRef, myOID,
-                  Extra_Entry[entryReceiveCont], sizeof(receiveMsg));
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
+			receiveMsg.continuation = ( void * ) sock;
+			receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
+		}
 
-  sockets[sock]->rx=true;
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
+			receiveMsg.continuation = ( void * ) sock;
+			receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
+		}
+
+	sockets[sock]->rx = true;
 }
 
 void
 Wireless::receive(int sock, int (*rcvcbckfn) (char*, int) )
 {
-  if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
-      || sockets[sock]->state != CONNECTION_CONNECTED) return;
+	if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
+			|| sockets[sock]->state != CONNECTION_CONNECTED) return;
 
-  sockets[sock]->rcvcbckfn=rcvcbckfn;
-  
-  TCPEndpointReceiveMsg receiveMsg(sockets[sock]->endpoint,
-                                   sockets[sock]->recvData,
-                                   1,sockets[sock]->recvBufSize);
-  receiveMsg.continuation = (void*)sock;
+	sockets[sock]->rcvcbckfn = rcvcbckfn;
 
-  receiveMsg.Send(ipstackRef, myOID,
-                  Extra_Entry[entryReceiveCont], sizeof(receiveMsg));
-  sockets[sock]->rx=true;
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
+			receiveMsg.continuation = ( void * ) sock;
+			receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
+		}
+
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
+			receiveMsg.continuation = ( void * ) sock;
+			receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
+		}
+
+	sockets[sock]->rx = true;
 }
 
 void
 Wireless::ReceiveCont(void* msg)
 {
-    TCPEndpointReceiveMsg* receiveMsg = (TCPEndpointReceiveMsg*)msg;
-    int sock = (int)(receiveMsg->continuation);
+	// get the socket index before casting the message into UDP or TCP form
+	antEnvMsg * Msg = ( antEnvMsg * ) msg;
+	int sock = ( int )( Msg->continuation );
 
-    if (receiveMsg->error != TCP_SUCCESS) {
-      sockets[sock]->state=CONNECTION_ERROR;
-      close(sock);
-      return;
-    }
-    sockets[sock]->recvSize=receiveMsg->sizeMin;
-    sockets[sock]->rcvcbckfn((char*)sockets[sock]->recvData,
-                             sockets[sock]->recvSize);
-    sockets[sock]->recvSize=0;
-    receive(sock);
+	if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
+			 || ( sockets[sock]->state != CONNECTION_CONNECTED && sockets[sock]->state != CONNECTION_CONNECTING ) )
+		return;
+
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointReceiveMsg * receiveMsg = ( TCPEndpointReceiveMsg * ) msg;
+			if ( receiveMsg->error != TCP_SUCCESS )
+				{
+					sockets[sock]->state = CONNECTION_ERROR;
+					close( sock );
+					return;
+				}
+
+			sockets[sock]->recvSize = receiveMsg->sizeMin;
+			if ( sockets[sock]->rcvcbckfn != NULL )
+				sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
+			sockets[sock]->recvSize = 0;
+
+		}
+
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointReceiveMsg * receiveMsg;
+			receiveMsg = ( UDPEndpointReceiveMsg * ) antEnvMsg::Receive( msg );
+			sockets[sock]->recvSize = receiveMsg->size;
+
+			if ( receiveMsg->error == UDP_SUCCESS )
+				{
+					// if this UDP connection is not connected yet, connect it
+					// to the address & port of the computer that sent this message.
+					// This allows us to send UDP messages to any address instead of
+					// hard-coding a specific address beforehand
+
+					if ( !strncmp( "connection request", ( char * ) sockets[sock]->recvData, 18 ) )
+						{
+							// clear this message from the receiving buffer
+							sockets[sock]->recvData += sockets[sock]->recvSize;
+
+							if ( sockets[sock]->state != CONNECTION_CONNECTED )
+								{
+									char caller[14];
+									receiveMsg->address.GetAsString( caller );
+									connect( sock, caller, receiveMsg->port );
+								}
+						}
+
+					else if ( sockets[sock]->rcvcbckfn != NULL )
+						sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
+
+				}
+
+			sockets[sock]->recvSize = 0;
+
+		}
+
+	receive( sock );
 }
 
 void
 Wireless::close(int sock)
 {
-  if (sockets[sock]->state == CONNECTION_CLOSED ||
-      sockets[sock]->state == CONNECTION_CLOSING) return;
+	if (sockets[sock]->state == CONNECTION_CLOSED ||
+			sockets[sock]->state == CONNECTION_CLOSING) return;
 
-  if (!(sockets[sock]->server_port>0 && sockets[sock]->daemon)) {
-    sockets[sock]->recvBuffer.UnMap();
-    antEnvDestroySharedBufferMsg receiveBufferMsg(sockets[sock]->recvBuffer);
-    receiveBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
-    sockets[sock]->sendBuffer.UnMap();
-    antEnvDestroySharedBufferMsg sendBufferMsg(sockets[sock]->sendBuffer);
-    sendBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
-  }
+	if (!(sockets[sock]->server_port>0 && sockets[sock]->daemon)) {
+		sockets[sock]->recvBuffer.UnMap();
+		antEnvDestroySharedBufferMsg receiveBufferMsg(sockets[sock]->recvBuffer);
+		receiveBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
+		sockets[sock]->sendBuffer.UnMap();
+		antEnvDestroySharedBufferMsg sendBufferMsg(sockets[sock]->sendBuffer);
+		sendBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
+	}
 
-  TCPEndpointCloseMsg closeMsg(sockets[sock]->endpoint);
-  closeMsg.continuation = (void*)sock;
+	if ( sockets[sock]->trType == SOCK_STREAM )
+		{
+			TCPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
+			closeMsg.continuation = ( void * ) sock;
+			closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
+		}
 
-  closeMsg.Send(ipstackRef, myOID,
-      Extra_Entry[entryCloseCont], sizeof(closeMsg));
+	else if ( sockets[sock]->trType == SOCK_DGRAM )
+		{
+			UDPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
+			closeMsg.continuation = ( void * ) sock;
+			closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
+		}
 
-  sockets[sock]->state = CONNECTION_CLOSING;
+	sockets[sock]->state = CONNECTION_CLOSING;
 }
 
 void
 Wireless::CloseCont(void* msg)
 {
-  TCPEndpointCloseMsg* closeMsg = (TCPEndpointCloseMsg*)msg;
-  int sock = (int)(closeMsg->continuation);
-	if(sockets[sock]==NULL)
+	antEnvMsg * closeMsg = ( antEnvMsg * ) msg;
+	int sock = ( int )( closeMsg->continuation );
+	if ( sockets[sock] == NULL )
 		return;
 
-  sockets[sock]->state = CONNECTION_CLOSED;
-  if (sockets[sock]->server_port>0
-      && sockets[sock]->daemon) {
-    // recycle if server
-    listen(sock, sockets[sock]->server_port);
-  } else {
-    delete(sockets[sock]);
-    sockets[sock]=NULL;
-    freeSockets.push_back(sock);
-  }
+	sockets[sock]->state = CONNECTION_CLOSED;
+	if ( sockets[sock]->server_port > 0 && sockets[sock]->daemon )
+		{
+			// recycle if server
+			listen( sock, sockets[sock]->server_port );
+		}
+
+	else
+		{
+			delete( sockets[sock] );
+			sockets[sock] = NULL;
+			freeSockets.push_back( sock );
+		}
 }
 
 /*! @file
  * @brief Interacts with the system to provide networking services
  * @author alokl (Creator)
+ * @author Erik Berglund and Bryan Johnson (UDP support)
  * 
  * @verbinclude CMPack_license.txt
  *
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.16 $
+ * $Revision: 1.19 $
  * $State: Exp $
- * $Date: 2003/12/11 05:49:31 $
+ * $Date: 2004/09/28 22:12:35 $
  */
 
Index: Wireless/Wireless.h
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/Wireless/Wireless.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- Wireless/Wireless.h	21 Sep 2003 19:43:41 -0000	1.14
+++ Wireless/Wireless.h	24 Mar 2004 06:38:21 -0000	1.15
@@ -22,6 +22,13 @@
  * - <a href="../RemoteProcess.html">Remote Processing OPENR</a>
  * Tekkotsu Wireless and Remote Processing OPENR provide different
  * interfaces to comparable wireless functionality.
+ *
+ * The networking interface needs more documentation.  It also needs a
+ * cleanup.  In the mean time, take a look at the TekkotsuMon objects
+ * in <i>Tekkotsu</i><tt>/Behaviors/Mon</tt>.  They all listen for new
+ * connections.  Unfortunately, at the momement there are no examples
+ * of outgoing connections, but it should give you a pretty good idea
+ * how to start moving.
  */
 class Wireless {
 public:
@@ -147,11 +154,11 @@
  * 
  * @verbinclude CMPack_license.txt
  *
- * $Author: alokl $
+ * $Author: ejt $
  * $Name:  $
- * $Revision: 1.14 $
- * $State: Rel $
- * $Date: 2003/09/21 19:43:41 $
+ * $Revision: 1.15 $
+ * $State: Exp $
+ * $Date: 2004/03/24 06:38:21 $
  */
 
 #endif // Wireless_h_DEFINED
Index: docs/behavior_header.h
===================================================================
RCS file: docs/behavior_header.h
diff -N docs/behavior_header.h
--- docs/behavior_header.h	23 Nov 2003 03:27:03 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,47 +0,0 @@
-//-*-c++-*-
-#ifndef INCLUDED_CLASSNAME_h_
-#define INCLUDED_CLASSNAME_h_
-
-#include "Behaviors/BehaviorBase.h"
-
-//! DESCRIPTION
-class CLASSNAME : public BehaviorBase {
-public:
-	//! constructor
-	CLASSNAME() : BehaviorBase() {}
-
-	virtual void DoStart() {
-		BehaviorBase::DoStart(); // do this first
-		// <your startup code here>
-	}
-
-	virtual void DoStop() {
-		// <your shutdown code here>
-		BehaviorBase::DoStop(); // do this last
-	}
-
-	virtual void processEvent(const EventBase& e) {
-		// <your event processing code here>
-		// you can delete this function if you don't use any events...
-	}
-
-	virtual std::string getName() const { return "CLASSNAME"; }
-
-	static std::string getClassDescription() { return "DESCRIPTION"; }
-	
-protected:
-	
-};
-
-/*! @file
- * @brief Defines CLASSNAME, which DESCRIPTION
- * @author YOURNAMEHERE (Creator)
- *
- * $Author: $
- * $Name:  $
- * $Revision: $
- * $State: $
- * $Date: $
- */
-
-#endif
Index: docs/builddocs
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/docs/builddocs,v
retrieving revision 1.11
retrieving revision 1.16
diff -u -d -r1.11 -r1.16
--- docs/builddocs	18 Jan 2004 10:16:59 -0000	1.11
+++ docs/builddocs	3 Sep 2004 15:56:34 -0000	1.16
@@ -15,7 +15,7 @@
 searchengine="SEARCHENGINE = NO";
 enabled_sections="ENABLED_SECTIONS += INTERNAL";
 input="$src";
-exclude="$input/TinyFTPD $input/ms $input/tools $input/contrib $input/deprecated $input/Shared/jpeg-6b $input/Motion/Spline.h $input/Motion/gvector.h $input/Motion/Path.h $input/SoundPlay/WAV.h $input/SoundPlay/WAV.cc $input/Wireless/ionetstream.h $input/Motion/Kinematics.h $input/Motion/Kinematics.cc $input/Motion/Geometry.h $input/Shared/Util.h";
+exclude="$input/TinyFTPD $input/ms $input/tools $input/contrib $input/deprecated $input/Shared/jpeg-6b $input/Motion/Spline.h $input/Motion/gvector.h $input/Motion/Path.h $input/SoundPlay/WAV.h $input/SoundPlay/WAV.cc $input/Wireless/ionetstream.h $input/Motion/OldKinematics.h $input/Motion/OldKinematics.cc $input/Motion/Geometry.h $input/Shared/Util.h $input/project/templates";
 
 while [ $# -gt 0 ] ; do
 	case $1 in
@@ -44,6 +44,8 @@
 echo $generate_treeview >> doxygenbuildcfg;
 echo $html_output >> doxygenbuildcfg;
 echo $searchengine >> doxygenbuildcfg;
+echo "GENERATE_TAGFILE = generated/tekkotsu.tag" >> doxygenbuildcfg
+echo "TAGFILES += generated/roboop.tag=roboop generated/newmat.tag=newmat" >> doxygenbuildcfg
 
 cancelupdate=0;
 if [ $update -ne 0 -a ! -d "$target" ] ; then
@@ -67,6 +69,12 @@
 fi;
 
 printf "Building documentation for \`\`$input'' ...";
+mv doxygenbuildcfg doxygenbuildcfg.tmp;
+touch doxygenbuildcfg;
+mkdir -p generated/html;
+doxygen newmat.doxycfg;
+doxygen roboop.doxycfg;
+mv doxygenbuildcfg.tmp doxygenbuildcfg
 doxygen doxygencfg ;
 printf "done\n";
 
Index: docs/doxygencfg
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/docs/doxygencfg,v
retrieving revision 1.31
retrieving revision 1.34
diff -u -d -r1.31 -r1.34
--- docs/doxygencfg	17 Mar 2004 03:00:07 -0000	1.31
+++ docs/doxygencfg	18 Oct 2004 16:59:27 -0000	1.34
@@ -1,4 +1,4 @@
-# Doxyfile 1.3.4
+# Doxyfile 1.3.9.1
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -23,7 +23,7 @@
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 2.1
+PROJECT_NUMBER         = 2.2
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 
@@ -31,16 +31,26 @@
 # where doxygen was started. If left blank the current directory will be used.
 
 #builddocs will set this in doxygenbuildcfg
-#OUTPUT_DIRECTORY       = /Users/ejt/todo/Tekkotsu/docs/generated
+#OUTPUT_DIRECTORY      = generated
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of source 
+# files, where putting all generated files in the same directory would otherwise 
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
 
 # 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.
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
@@ -68,6 +78,17 @@
 
 REPEAT_BRIEF           = YES
 
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
 # 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.
@@ -91,10 +112,21 @@
 # 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.
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
 
 STRIP_FROM_PATH        = 
 
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_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.
@@ -105,7 +137,7 @@
 # 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.
+# explicit @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = NO
 
@@ -126,7 +158,7 @@
 
 # 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.
+# re-implements.
 
 INHERIT_DOCS           = YES
 
@@ -201,6 +233,13 @@
 
 EXTRACT_LOCAL_CLASSES  = YES
 
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = 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 
@@ -241,7 +280,7 @@
 # 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.
+# and Mac users are advised to set this option to NO.
 
 CASE_SENSE_NAMES       = YES
 
@@ -269,6 +308,23 @@
 
 SORT_MEMBER_DOCS       = YES
 
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
 # 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.
@@ -296,7 +352,7 @@
 # The ENABLED_SECTIONS tag can be used to enable conditional 
 # documentation sections, marked by \if sectionname ... \endif.
 
-ENABLED_SECTIONS       =
+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 
@@ -314,6 +370,12 @@
 
 SHOW_USED_FILES        = YES
 
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
@@ -372,7 +434,7 @@
 # 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
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
 
 FILE_PATTERNS          = 
 
@@ -386,8 +448,9 @@
 # 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.
 
-#builddocs will set this in doxygenbuildcfg
-#EXCLUDE                = 
+-#builddocs will set this in doxygenbuildcfg
+-#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.
@@ -402,6 +465,9 @@
                          */Vision/colors.h \
                          */docs/*.h \
                          */docs/*.cc \
+                         */Shared/newmat/* \
+                         */Motion/roboop/* \
+                         */project/*
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or 
 # directories that contain example code fragments that are included (see 
@@ -434,10 +500,20 @@
 # 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.
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
 
 INPUT_FILTER           = 
 
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
 # 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).
@@ -449,7 +525,9 @@
 #---------------------------------------------------------------------------
 
 # 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.
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
 
 SOURCE_BROWSER         = YES
 
@@ -542,7 +620,9 @@
 # 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
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
 
 HTML_STYLESHEET        = html/doxygen.css
 
@@ -562,7 +642,7 @@
 # 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.
+# written to the html output directory.
 
 CHM_FILE               = 
 
@@ -624,7 +704,7 @@
 # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
 # generate Latex output.
 
-GENERATE_LATEX         = YES
+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 
@@ -698,7 +778,7 @@
 #---------------------------------------------------------------------------
 
 # 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 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
 # other RTF readers or editors.
 
 GENERATE_RTF           = NO
@@ -725,7 +805,7 @@
 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 
+# config file, i.e. a series of assignments. You only have to provide 
 # replacements, missing definitions are set to their default value.
 
 RTF_STYLESHEET_FILE    = 
@@ -769,9 +849,7 @@
 
 # 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.
+# the code including all documentation.
 
 GENERATE_XML           = NO
 
@@ -793,6 +871,13 @@
 
 XML_DTD                = 
 
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
 #---------------------------------------------------------------------------
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
@@ -883,19 +968,20 @@
 # 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.
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
 
 PREDEFINED             = DEBUG \
-                         PLATFORM_APERIOS
+                         PLATFORM_APERIOS \
+                         TGT_ERS7
 
 # 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      = REGDEFNOMEM \
-                         REGDEF \
-                         REGIMP
+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 
@@ -906,7 +992,7 @@
 SKIP_FUNCTION_MACROS   = NO
 
 #---------------------------------------------------------------------------
-# Configuration::addtions related to external references   
+# Configuration::additions related to external references   
 #---------------------------------------------------------------------------
 
 # The TAGFILES option can be used to specify one or more tagfiles. 
@@ -924,12 +1010,14 @@
 # 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               = 
+#builddocs will set this in doxygenbuildcfg
+#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       = 
+#builddocs will set this in doxygenbuildcfg
+#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 
@@ -955,7 +1043,7 @@
 # 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 
+# option is superseded 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
@@ -988,7 +1076,7 @@
 COLLABORATION_GRAPH    = NO
 
 # 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 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
 # Language.
 
 UML_LOOK               = NO
@@ -1048,7 +1136,7 @@
 # the specified constraint. Beware that most browsers cannot cope with very 
 # large images.
 
-MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_WIDTH    = 800
 
 # 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 
@@ -1056,7 +1144,7 @@
 # the specified constraint. Beware that most browsers cannot cope with very 
 # large images.
 
-MAX_DOT_GRAPH_HEIGHT   = 512
+MAX_DOT_GRAPH_HEIGHT   = 768
 
 # 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 
@@ -1082,7 +1170,7 @@
 DOT_CLEANUP            = YES
 
 #---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine   
+# Configuration::additions related to the search engine   
 #---------------------------------------------------------------------------
 
 # The SEARCHENGINE tag specifies whether or not a search engine should be 
Index: docs/gpl.txt
===================================================================
RCS file: docs/gpl.txt
diff -N docs/gpl.txt
--- docs/gpl.txt	5 Dec 2003 20:26:48 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,340 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
Index: docs/header.h
===================================================================
RCS file: docs/header.h
diff -N docs/header.h
--- docs/header.h	14 Oct 2002 01:13:40 -0000	1.3
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,24 +0,0 @@
-//-*-c++-*-
-#ifndef INCLUDED_CLASSNAME_h_
-#define INCLUDED_CLASSNAME_h_
-
-//! description of CLASSNAME
-class CLASSNAME {
-public:
-	
-protected:
-	
-};
-
-/*! @file
- * @brief 
- * @author YOURNAMEHERE (Creator)
- *
- * $Author: $
- * $Name:  $
- * $Revision: $
- * $State: $
- * $Date: $
- */
-
-#endif
Index: docs/implementation.cc
===================================================================
RCS file: docs/implementation.cc
diff -N docs/implementation.cc
--- docs/implementation.cc	23 Nov 2003 03:26:46 -0000	1.4
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,13 +0,0 @@
-#include "CLASSNAME.h"
-
-/*! @file
- * @brief 
- * @author YOURNAMEHERE (Creator)
- *
- * $Author: $
- * $Name:  $
- * $Revision: $
- * $State: $
- * $Date: $
- */
-
Index: docs/newmat.doxycfg
===================================================================
RCS file: docs/newmat.doxycfg
diff -N docs/newmat.doxycfg
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/newmat.doxycfg	20 Jul 2004 17:56:10 -0000	1.2
@@ -0,0 +1,16 @@
+@INCLUDE = doxygencfg
+
+PROJECT_NAME = newmat
+PROJECT_NUMBER = 11b
+INPUT = ../Shared/newmat
+EXCLUDE = 
+EXCLUDE_PATTERNS = */extra/*
+OUTPUT_DIRECTORY = generated/html
+EXTRACT_ALL = YES
+ALWAYS_DETAILED_SEC = NO
+GENERATE_TREEVIEW = YES
+HTML_OUTPUT = newmat
+SEARCHENGINE = YES
+GENERATE_TAGFILE = generated/newmat.tag
+HTML_FOOTER = newmatfoot.html
+PREDEFINED += use_namespace
\ No newline at end of file
Index: docs/newmatfoot.html
===================================================================
RCS file: docs/newmatfoot.html
diff -N docs/newmatfoot.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/newmatfoot.html	20 Jul 2004 17:57:01 -0000	1.1
@@ -0,0 +1,48 @@
+</td></tr></tbody></table>
+
+  <br>
+	<table cellpadding="2" cellspacing="2" border="0" style="text-align: left; width: 100%; color: rgb(0, 0, 0);">
+		<tbody>
+			<tr>
+				<td style="vertical-align: top;"><small>
+						<b><a href="http://www.robertnz.net/nm_intro.htm">$projectname$projectnumber</a><br></b>
+					</small>
+				</td>
+				<td style="vertical-align: top; text-align: right; font-style: italic;">
+					<small>
+						Generated $datetime by <a href="http://www.doxygen.org/">Doxygen</a> $doxygenversion
+					</small>
+					<script type="text/javascript" language="javascript">
+						<!--
+						s="na";c="na";j="na";f=""+escape(document.referrer)
+						//-->
+					</script>
+					<script type="text/javascript" language="javascript1.2">
+						<!--
+						s=screen.width;v=navigator.appName
+						if (v != "Netscape") {c=screen.colorDepth}
+						else {c=screen.pixelDepth}
+						j=navigator.javaEnabled()
+						//-->
+					</script>
+					<script type="text/javascript" language="javascript">
+						<!--
+						function pr(n) {document.write(n,"\n");}
+						NS2Ch=0
+						if (navigator.appName == "Netscape" &&
+						navigator.appVersion.charAt(0) == "2") {NS2Ch=1}
+						if (NS2Ch == 0) {
+						r="size="+s+"&colors="+c+"&referer="+f+"&java="+j+"&stamp="+(new Date()).getTime()+""
+						pr("<IMG BORDER=0 width=16 height=16 align=\"middle\" SRC=\"http://aibo2.boltz.cs.cmu.edu/head.gif?"+r+"\">")}
+						//-->
+					</script> 
+					
+					<noscript>
+						<img src="http://aibo2.boltz.cs.cmu.edu/head.gif" border="0" width=16 height=16 align="middle">
+					</noscript>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+</body>
+</html>
Index: docs/roboop.doxycfg
===================================================================
RCS file: docs/roboop.doxycfg
diff -N docs/roboop.doxycfg
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/roboop.doxycfg	20 Jul 2004 17:56:10 -0000	1.2
@@ -0,0 +1,17 @@
+@INCLUDE = doxygencfg
+
+PROJECT_NAME = ROBOOP
+PROJECT_NUMBER = 1.21a
+INPUT = ../Motion/roboop
+EXCLUDE = 
+EXCLUDE_PATTERNS = */extra/*
+OUTPUT_DIRECTORY = generated/html
+EXTRACT_ALL = YES
+ALWAYS_DETAILED_SEC = NO
+GENERATE_TREEVIEW = YES
+HTML_OUTPUT = roboop
+SEARCHENGINE = YES
+TAGFILES += generated/newmat.tag=../newmat
+GENERATE_TAGFILE = generated/roboop.tag
+HTML_FOOTER = roboopfoot.html
+INCLUDE_PATH = ../Shared/newmat
\ No newline at end of file
Index: docs/roboopfoot.html
===================================================================
RCS file: docs/roboopfoot.html
diff -N docs/roboopfoot.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/roboopfoot.html	20 Jul 2004 17:57:01 -0000	1.1
@@ -0,0 +1,48 @@
+</td></tr></tbody></table>
+
+  <br>
+	<table cellpadding="2" cellspacing="2" border="0" style="text-align: left; width: 100%; color: rgb(0, 0, 0);">
+		<tbody>
+			<tr>
+				<td style="vertical-align: top;"><small>
+						<b><a href="http://www.cours.polymtl.ca/roboop/">$projectname</a> v$projectnumber<br></b>
+					</small>
+				</td>
+				<td style="vertical-align: top; text-align: right; font-style: italic;">
+					<small>
+						Generated $datetime by <a href="http://www.doxygen.org/">Doxygen</a> $doxygenversion
+					</small>
+					<script type="text/javascript" language="javascript">
+						<!--
+						s="na";c="na";j="na";f=""+escape(document.referrer)
+						//-->
+					</script>
+					<script type="text/javascript" language="javascript1.2">
+						<!--
+						s=screen.width;v=navigator.appName
+						if (v != "Netscape") {c=screen.colorDepth}
+						else {c=screen.pixelDepth}
+						j=navigator.javaEnabled()
+						//-->
+					</script>
+					<script type="text/javascript" language="javascript">
+						<!--
+						function pr(n) {document.write(n,"\n");}
+						NS2Ch=0
+						if (navigator.appName == "Netscape" &&
+						navigator.appVersion.charAt(0) == "2") {NS2Ch=1}
+						if (NS2Ch == 0) {
+						r="size="+s+"&colors="+c+"&referer="+f+"&java="+j+"&stamp="+(new Date()).getTime()+""
+						pr("<IMG BORDER=0 width=16 height=16 align=\"middle\" SRC=\"http://aibo2.boltz.cs.cmu.edu/head.gif?"+r+"\">")}
+						//-->
+					</script> 
+					
+					<noscript>
+						<img src="http://aibo2.boltz.cs.cmu.edu/head.gif" border="0" width=16 height=16 align="middle">
+					</noscript>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+</body>
+</html>
Index: docs/benchmarks/profilerun_ERS210A_2.2.txt
===================================================================
RCS file: docs/benchmarks/profilerun_ERS210A_2.2.txt
diff -N docs/benchmarks/profilerun_ERS210A_2.2.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/benchmarks/profilerun_ERS210A_2.2.txt	18 Oct 2004 20:33:52 -0000	1.1
@@ -0,0 +1,119 @@
+Setup:
+  Default build for ERS-2xx (TGT_ERS2xx)
+  Pink ball in view (8.5in from snout)
+  Press power button, start timer
+  Telnet to system console (port 59000)
+  Connect ControllerGUI
+  STARTUP script:
+    Launch StareAtBallBehavior (leave E-Stop ON)
+    Navigate to Status Reports -> Profiler
+  Wait until 5 minutes from initial press of power button.
+  Recorded profiler run shown below
+ 
+~~~ Main: ~~~
+Profiling information since: 18.676059 to 298.629764
+PowerEvent():
+        42 calls
+        0.676500 ms avg
+        0.685429 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        6266.471500 ms avg inter (0.159579 fps)
+        11424.051758 ms exp.avg (0.087535 fps)
+        Exec: 0 0 26 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 0 0 0 0 3 0 4 0 0 0 0 1 0 5 12 0 0 1 1 0 1 0 2 0 11
+ReadySendJoints():
+        2163 calls
+        0.470877 ms avg
+        0.626251 ms exp.avg
+        0.001419 ms avg child time (0.300000%)
+        128.152637 ms avg inter (7.803195 fps)
+        127.880913 ms exp.avg (7.819775 fps)
+        Exec: 0 1 1859 301 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 1 2 0 0 0 0 0 0 0 2156 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotSensorFrame():
+        8636 calls
+        0.628175 ms avg
+        0.584827 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        32.085828 ms avg inter (31.166408 fps)
+        31.487766 ms exp.avg (31.758366 fps)
+        Exec: 0 0 6846 1789 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 2 0 14 6891 1726 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotAudio():
+        8636 calls
+        0.894791 ms avg
+        0.906565 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        32.009507 ms avg inter (31.240719 fps)
+        32.838280 ms exp.avg (30.452263 fps)
+        Exec: 0 0 5930 2672 33 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 1 3 8616 14 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotImage():
+        6889 calls
+        10.563204 ms avg
+        10.948741 ms exp.avg
+        8.605200 ms avg child time (81.400000%)
+        40.129944 ms avg inter (24.919048 fps)
+        39.881496 ms exp.avg (25.074284 fps)
+        Exec: 0 0 0 5 11 5145 1727 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 1 1 4 6881 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+BallDetection::processEvent():
+        20667 calls
+        2.868400 ms avg
+        2.783488 ms exp.avg
+        2.695050 ms avg child time (93.900000%)
+        13.371671 ms avg inter (74.784968 fps)
+        12.105479 ms exp.avg (82.607224 fps)
+        Exec: 31 13489 268 6 0 6862 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 6567 333 5 0 6863 14 6770 113 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RegionGenerator::calcImage(...):
+        6873 calls
+        8.103973 ms avg
+        8.517103 ms exp.avg
+        4.628215 ms avg child time (57.100000%)
+        40.098334 ms avg inter (24.938692 fps)
+        39.857632 ms exp.avg (25.089296 fps)
+        Exec: 0 0 0 0 0 6865 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 3 6869 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RLEGenerator::calcImage(...):
+        6873 calls
+        4.628215 ms avg
+        4.651764 ms exp.avg
+        2.974546 ms avg child time (64.200000%)
+        40.099341 ms avg inter (24.938065 fps)
+        39.857174 ms exp.avg (25.089586 fps)
+        Exec: 0 0 0 0 6420 453 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 3 6869 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+SegmentedColorGenerator::calcImage(...):
+        6873 calls
+        2.974546 ms avg
+        2.904782 ms exp.avg
+        0.031639 ms avg child time (1.000000%)
+        40.102083 ms avg inter (24.936360 fps)
+        39.858536 ms exp.avg (25.088730 fps)
+        Exec: 0 0 0 0 6871 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 3 6869 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RawCameraGenerator::calcImage(...):
+        20619 calls
+        0.010546 ms avg
+        0.007385 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        13.364430 ms avg inter (74.825490 fps)
+        11.141737 ms exp.avg (89.752609 fps)
+        Exec: 13609 6900 103 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 1317 12218 197 14 0 0 0 3 6869 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Bucket distribution (in ms):
+        0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
+~~~ Motion: ~~~
+Profiling information since: 18.676521 to 298.640604
+ReadySendJoints():
+        8646 calls
+        1.713944 ms avg
+        1.613711 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        32.031116 ms avg inter (31.219642 fps)
+        32.116814 ms exp.avg (31.136337 fps)
+        Exec: 0 0 0 8535 94 1 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 8629 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Bucket distribution (in ms):
+        0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
Index: docs/benchmarks/profilerun_ERS7_2.2.txt
===================================================================
RCS file: docs/benchmarks/profilerun_ERS7_2.2.txt
diff -N docs/benchmarks/profilerun_ERS7_2.2.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/benchmarks/profilerun_ERS7_2.2.txt	18 Oct 2004 20:33:52 -0000	1.1
@@ -0,0 +1,119 @@
+Setup:
+  Default build for ERS-7 (TGT_ERS7)
+  Pink ball in view (8.5in from snout)
+  Press power button, start timer
+  Telnet to system console (port 59000)
+  Connect ControllerGUI
+  STARTUP script:
+    Launch StareAtBallBehavior (leave E-Stop ON)
+    Navigate to Status Reports -> Profiler
+  Wait until 5 minutes from initial press of power button.
+  Recorded profiler run shown below
+
+~~~ Main: ~~~
+Profiling information since: 16.044272 to 297.692924
+PowerEvent():
+        16 calls
+        0.227937 ms avg
+        0.203721 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        17299.984500 ms avg inter (0.057804 fps)
+        19084.355469 ms exp.avg (0.052399 fps)
+        Exec: 0 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 12
+ReadySendJoints():
+        1 calls
+        0.008000 ms avg
+        0.008000 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        0.000000 ms avg inter (Inf fps)
+        0.000000 ms exp.avg (Inf fps)
+        Exec: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotSensorFrame():
+        8734 calls
+        0.253030 ms avg
+        0.223205 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        32.042992 ms avg inter (31.208072 fps)
+        31.987932 ms exp.avg (31.261789 fps)
+        Exec: 0 817 7832 84 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 1 1 0 8727 2 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotAudio():
+        8735 calls
+        0.459267 ms avg
+        0.659022 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        31.991896 ms avg inter (31.257916 fps)
+        31.965643 ms exp.avg (31.283588 fps)
+        Exec: 0 5 7048 1682 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 2 0 2 8729 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+GotImage():
+        8377 calls
+        3.168781 ms avg
+        3.180732 ms exp.avg
+        2.439745 ms avg child time (76.900000%)
+        33.355267 ms avg inter (29.980273 fps)
+        33.095577 ms exp.avg (30.215519 fps)
+        Exec: 0 0 56 12 8307 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 3 0 0 6942 1430 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+BallDetection::processEvent():
+        25131 calls
+        0.813248 ms avg
+        0.689401 ms exp.avg
+        0.727022 ms avg child time (89.300000%)
+        11.119712 ms avg inter (89.930384 fps)
+        9.264021 ms exp.avg (107.944489 fps)
+        Exec: 12359 4461 2 0 8308 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 67 8375 2 2 8310 1 0 7044 1328 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RegionGenerator::calcImage(...):
+        8309 calls
+        2.198916 ms avg
+        2.196095 ms exp.avg
+        1.990231 ms avg child time (90.500000%)
+        33.355898 ms avg inter (29.979706 fps)
+        33.108459 ms exp.avg (30.203762 fps)
+        Exec: 0 0 0 5409 2900 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 1 0 0 6888 1419 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RLEGenerator::calcImage(...):
+        8309 calls
+        1.990231 ms avg
+        1.986546 ms exp.avg
+        1.620538 ms avg child time (81.400000%)
+        33.356003 ms avg inter (29.979612 fps)
+        33.108505 ms exp.avg (30.203718 fps)
+        Exec: 0 0 0 8287 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 1 0 0 6888 1419 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+SegmentedColorGenerator::calcImage(...):
+        8309 calls
+        1.620538 ms avg
+        1.623055 ms exp.avg
+        0.015321 ms avg child time (0.900000%)
+        33.355990 ms avg inter (29.979623 fps)
+        33.108345 ms exp.avg (30.203865 fps)
+        Exec: 0 0 0 8306 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 1 0 0 6888 1419 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+RawCameraGenerator::calcImage(...):
+        24927 calls
+        0.005107 ms avg
+        0.004481 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        11.117531 ms avg inter (89.948028 fps)
+        9.142442 ms exp.avg (109.379967 fps)
+        Exec: 16710 8217 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 8302 8316 0 0 1 0 0 6888 1419 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Bucket distribution (in ms):
+        0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
+~~~ Motion: ~~~
+Profiling information since: 16.044388 to 297.699604
+ReadySendJoints():
+        8728 calls
+        1.114224 ms avg
+        0.991145 ms exp.avg
+        0.000000 ms avg child time (0.000000%)
+        32.062669 ms avg inter (31.188920 fps)
+        32.040295 ms exp.avg (31.210699 fps)
+        Exec: 0 0 3 8706 2 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        Inter: 0 0 0 0 0 0 0 8710 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Bucket distribution (in ms):
+        0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
Index: docs/html/doxygen.css
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/docs/html/doxygen.css,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- docs/html/doxygen.css	10 Feb 2004 01:47:12 -0000	1.4
+++ docs/html/doxygen.css	18 Oct 2004 17:01:38 -0000	1.5
@@ -4,42 +4,87 @@
 }
 H2 {
 	font-family: Geneva, Arial, Helvetica, sans-serif;
+	font-size: 20px;
+}
+P {
+	width: 620px;
 }
 CAPTION { font-weight: bold }
-DIV.qindex { width: 100%;
-             background-color: #eeeeff;
-             border: 1px solid #B0B0B0;
-             text-align: center;
-             margin: 2px;
-             padding: 2px;
-             width: 620px;
-             align: center; margin-left: auto; margin-right: auto; 
+DIV.qindex {
+	background-color: #eeeeff;
+	border: 1px solid #b0b0b0;
+	text-align: center;
+	margin: 2px;
+	padding: 2px;
+	line-height: 140%;
+    width: 620px;
+    align: center;
+    margin-left: auto;
+    margin-right: auto; 
+	font-size: smaller;
+}
+DIV.nav {
+	width: 100%;
+	background-color: #eeeeff;
+	border: 1px solid #b0b0b0;
+	text-align: center;
+	margin: 2px;
+	padding: 2px;
+	line-height: 140%;
+}
+A.qindex {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D;
+}
+A.qindex:visited {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D
+}
+A.qindex:hover {
+	text-decoration: none;
+	background-color: #ddddff;
+}
+A.qindexHL {
+	text-decoration: none;
+	font-weight: bold;
+	background-color: #6666cc;
+	color: #ffffff;
+	border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+	text-decoration: none;
+	background-color: #6666cc;
+	color: #ffffff;
 }
-A.qindex { text-decoration: none; font-weight: bold; color: #0000ee }
-A.qindex:visited { text-decoration: none; font-weight: bold; color: #0000ee }
-A.qindex:hover { text-decoration: none; background-color: #ddddff }
-A.qindexHL { text-decoration: none; font-weight: bold;
-             background-color: #6666cc;
-             color: #ffffff
-           }
-A.qindexHL:hover { text-decoration: none; background-color: #6666cc; color: #ffffff }
 A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
-A.el { text-decoration: none; font-weight: bold; color: #082090 }
-A.el:visited { text-decoration: none; font-weight: bold; color: #000058 }
+A.el { text-decoration: none; font-weight: bold }
 A.elRef { font-weight: bold }
-A.code { text-decoration: none; font-weight: normal; color: #4444ee }
-A.codeRef { font-weight: normal; color: #4444ee }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
 A:hover { text-decoration: none; background-color: #f2f2ff }
 DL.el { margin-left: -1cm }
-DIV.fragment {
-	width: 98%;
+.fragment {
+       font-family: monospace;
+       font-size: 9pt;
+}
+PRE.fragment {
 	border: 1px solid #CCCCCC;
 	background-color: #f5f5f5;
-	padding-left: 4px;
-	margin: 4px;
+	margin-top: 4px;
+	margin-bottom: 4px;
+	margin-left: 2px;
+	margin-right: 8px;
+	padding-left: 6px;
+	padding-right: 6px;
+	padding-top: 4px;
+	padding-bottom: 4px;
 }
 DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
-TD.md { background-color: #f2f2ff; font-weight: bold; text-align: right; }
+TD.md { background-color: #f2f2ff; font-weight: bold; }
 TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; }
 TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; }
 DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }
@@ -50,29 +95,31 @@
 	margin-right: 20px;
 	margin-left: 20px;
 }
-TD.indexkey { 
-   background-color: #eeeeff; 
-   font-weight: bold; 
-   padding-right  : 10px; 
-   padding-top    : 2px; 
-   padding-left   : 10px; 
-   padding-bottom : 2px; 
-   margin-left    : 0px; 
-   margin-right   : 0px; 
-   margin-top     : 2px; 
-   margin-bottom  : 2px  
+TD.indexkey {
+	background-color: #eeeeff;
+	font-weight: bold;
+	padding-right  : 10px;
+	padding-top    : 2px;
+	padding-left   : 10px;
+	padding-bottom : 2px;
+	margin-left    : 0px;
+	margin-right   : 0px;
+	margin-top     : 2px;
+	margin-bottom  : 2px;
+	border: 1px solid #CCCCCC;
 }
-TD.indexvalue { 
-   background-color: #eeeeff; 
-   font-style: italic; 
-   padding-right  : 10px; 
-   padding-top    : 2px; 
-   padding-left   : 10px; 
-   padding-bottom : 2px; 
-   margin-left    : 0px; 
-   margin-right   : 0px; 
-   margin-top     : 2px; 
-   margin-bottom  : 2px  
+TD.indexvalue {
+	background-color: #eeeeff;
+	font-style: italic;
+	padding-right  : 10px;
+	padding-top    : 2px;
+	padding-left   : 10px;
+	padding-bottom : 2px;
+	margin-left    : 0px;
+	margin-right   : 0px;
+	margin-top     : 2px;
+	margin-bottom  : 2px;
+	border: 1px solid #CCCCCC;
 }
 TR.memlist {
    background-color: #f0f0f0; 
@@ -91,14 +138,14 @@
 	border: 1px solid #808080;
 	background-color: #f2f2ff;
 	border-bottom-style: none;
-	width: 100%
 }
 .mdRow {
 	padding: 8px 20px;
 }
 .mdescLeft {
+       padding: 0px 8px 4px 8px;
 	font-size: smaller;
-	font-family: Arial, Helvetica, sans-serif;
+	font-style: italic;
 	background-color: #F4F4F4;
 	padding-left: 8px;
 	border-top: 1px none #E0E0E0;
@@ -108,18 +155,15 @@
 	margin: 0px;
 }
 .mdescRight {
+       padding: 0px 8px 4px 8px;
 	font-size: smaller;
-	font-family: Arial, Helvetica, sans-serif;
 	font-style: italic;
 	background-color: #F4F4F4;
-	padding-left: 4px;
 	border-top: 1px none #E0E0E0;
 	border-right: 1px none #B0B0B0;
 	border-bottom: 1px solid #D0D0D0;
 	border-left: 1px none #E0E0E0;
 	margin: 0px;
-	padding-bottom: 0px;
-	padding-right: 8px;
 }
 .memItemLeft {
 	padding: 1px 0px 0px 8px;
@@ -128,38 +172,90 @@
 	border-right-width: 1px;
 	border-bottom-width: 1px;
 	border-left-width: 1px;
-	border-top-style: solid;
 	border-top-color: #D0D0D0;
 	border-right-color: #E0E0E0;
 	border-bottom-color: #E0E0E0;
 	border-left-color: #B0B0B0;
+	border-top-style: solid;
 	border-right-style: solid;
 	border-bottom-style: none;
 	border-left-style: none;
 	background-color: #F4F4F4;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	font-size: 12px;
+	font-size: 14px;
 }
 .memItemRight {
-	padding: 1px 0px 0px 8px;
+	padding: 1px 8px 0px 8px;
 	margin: 4px;
 	border-top-width: 1px;
 	border-right-width: 1px;
 	border-bottom-width: 1px;
 	border-left-width: 1px;
+	border-top-color: #D0D0D0;
+	border-right-color: #B0B0B0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
 	border-top-style: solid;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #F4F4F4;
+	font-size: 14px;
+}
+.memTemplItemLeft {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #D0D0D0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #B0B0B0;
+	border-top-style: none;
+	border-right-style: solid;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #F4F4F4;
+	font-size: 14px;
+}
+.memTemplItemRight {
+	padding: 1px 8px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
 	border-top-color: #D0D0D0;
 	border-right-color: #B0B0B0;
 	border-bottom-color: #E0E0E0;
 	border-left-color: #E0E0E0;
+	border-top-style: none;
 	border-right-style: none;
 	border-bottom-style: none;
 	border-left-style: none;
 	background-color: #F4F4F4;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	font-size: 13px;
+	font-size: 14px;
+	}
+.memTemplParams {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #D0D0D0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #B0B0B0;
+	border-top-style: solid;
+	border-right-style: solid;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #F4F4F4;
+	font-size: 14px;
 }
-.search     { color: #000000;
+.search     { color: #003399;
               font-weight: bold;
 }
 FORM.search {
Index: docs/html/index.html
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/docs/html/index.html,v
retrieving revision 1.30
retrieving revision 1.32
diff -u -d -r1.30 -r1.32
--- docs/html/index.html	17 Mar 2004 03:04:07 -0000	1.30
+++ docs/html/index.html	19 Oct 2004 08:28:01 -0000	1.32
@@ -52,16 +52,19 @@
     </tr>
   </tbody>
 </table>
-<div class="qindex"><a class="qindexHL" href="main.html">Main&nbsp;Page</a>
-| <a class="qindex" href="namespaces.html">Namespace List</a> | <a
- class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a
- class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a
- class="qindex" href="annotated.html">Class&nbsp;List</a> | <a
- class="qindex" href="files.html">File&nbsp;List</a> | <a
- class="qindex" href="namespacemembers.html">Namespace&nbsp;Members</a>
-| <a class="qindex" href="functions.html">Class&nbsp;Members</a> | <a
- class="qindex" href="globals.html">File&nbsp;Members</a> | <a
- class="qindex" href="pages.html">Related&nbsp;Pages</a></div>
+<div class="qindex">
+<a class="qindexHL" href="main.html">Main&nbsp;Page</a> | 
+<a class="qindex" href="namespaces.html">Namespace List</a> | 
+<a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | 
+<a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | 
+<a class="qindex" href="annotated.html">Class&nbsp;List</a> | 
+<a class="qindex" href="dirs.html">Directories</a> | 
+<a class="qindex" href="files.html">File&nbsp;List</a> | 
+<a class="qindex" href="namespacemembers.html">Namespace&nbsp;Members</a> | 
+<a class="qindex" href="functions.html">Class&nbsp;Members</a> | 
+<a class="qindex" href="globals.html">File&nbsp;Members</a> | 
+<a class="qindex" href="pages.html">Related&nbsp;Pages</a>
+</div>
 <center>
 <h1>Tekkotsu Source Documentation</h1>
 </center>
@@ -121,8 +124,8 @@
 static copies of the documentation, there are two formats:<br>
       </p>
       <ul style="margin-left: 40px;">
-        <li><a href="../media/Tekkotsu_doc_2.1.tar.gz">HTML</a> (v2.1,
-3.7MB)</li>
+        <li><a href="../media/Tekkotsu_doc_2.2.tar.gz">HTML</a> (v2.2,
+6.4MB)</li>
       </ul>
       <div style="margin-left: 40px;">If you're using the most recent
 version from the <a href="http://cvs.tekkotsu.org/">CVS repository</a>,
@@ -132,6 +135,21 @@
       </div>
       <h3>External Documentation:<br>
       </h3>
+      <p style="margin-left: 40px;">
+We make use of two independent libraries: the <a
+href="http://www.robertnz.net/nm_intro.htm" target="_top">newmat</a> matrix library
+and the <a href="http://www.cours.polymtl.ca/roboop/" target="_top">ROBOOP</a>
+kinematics library.  We mirror their own doxygen documentation on our
+site so that our documentation can link to it.
+</p>
+      <p style="margin-left: 40px;">
+You can directly access these libraries' documentation with these links:
+<ul style="margin-left: 40px;">
+<li><a href="newmat/index.html" target="_top">newmat</a> Documentation
+<li><a href="roboop/index.html" target="_top">ROBOOP</a> Documentation
+</ul>
+</p>
+						</p>
       <p style="margin-left: 40px;"> This code is originally based on
 an early version of CMU's
 2002 Legged RoboSoccer entry, <a
Index: project/Makefile
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/Makefile,v
retrieving revision 1.61
retrieving revision 1.83
diff -u -d -r1.61 -r1.83
--- project/Makefile	17 Mar 2004 03:40:55 -0000	1.61
+++ project/Makefile	14 Oct 2004 20:22:51 -0000	1.83
@@ -32,21 +32,39 @@
 # default: OFF (empty string) - any non-empty string is ON
 STRICT_MEMSTICK_IMAGE ?=
 
+# What model are you targeting?  This will look at the
+# $TEKKOTSU_ROOT/TARGET_MODEL file to find out.  If the file is not
+# found, it is created with the default setting TGT_ERS2xx.  change
+# the target model, make will automatically recompile everything for
+# you.
+# Legal values: TGT_ERS210 TGT_ERS220 TGT_ERS2xx TGT_ERS7
+TEKKOTSU_TARGET_MODEL ?= TGT_ERS7
+
+# What OS is this going to be running under?
+# Right now, the only choice is Aperios, but in the future we may
+# support running under linux systems, either as simulation for
+# AIBOs, or direct support for linux-based robots.
+TEKKOTSU_TARGET_PLATFORM ?= PLATFORM_APERIOS
+
+# This can be nice if you want to use more to page through errors
+# if they occur.  Otherwise, try using cat instead.
+TEKKOTSU_LOGVIEW ?= $(if $(findstring Darwin,$(shell uname)),cat,more)
+
+# These control the location that the temporary object files will
+# be stored.
+TEKKOTSU_BUILDDIR ?= $(TEKKOTSU_ROOT)/build
+PROJECT_BUILDDIR ?= build
+# or perhaps you would like something like this better:
+#TEKKOTSU_BUILDDIR ?= /tmp/tekkotsu_build_$(USER)
+#PROJECT_BUILDDIR ?= /tmp/project_build_$(USER)
+
+
 
 #############  MAKEFILE VARIABLES  ################
 # Change these right here in the Makefile
 
 # Want any other libraries passed to the compiler?  Put them here.
-LIBS=-lObjectComm -lOPENR -lInternet -lantMCOOP
-
-# What model AIBO are you targeting?  This will look at the
-# $TEKKOTSU_ROOT/TARGET_MODEL file to find out.  If the file is not
-# found, it is created with the default setting TGT_ERS2xx.
-# change the target model, make will automatically recompile
-# everything for you.
-# Legal values: TGT_ERS210 TGT_ERS220 TGT_ERS2xx 
-# If you want to change this, edit the TARGET_MODEL file, not this line!
-TEKKOTSU_TARGET_MODEL:=$(shell if [ ! -r "$(TEKKOTSU_ROOT)/TARGET_MODEL" ] ; then echo "TGT_ERS2xx" > $(TEKKOTSU_ROOT)/TARGET_MODEL ; fi ; cat $(TEKKOTSU_ROOT)/TARGET_MODEL )
+LIBS=-lObjectComm -lOPENR -lInternet -lantMCOOP -lERA201D1
 
 # Would you like some more compiler flags?  We like lots of warnings.
 # There are some files with exceptions to these flags - MMCombo*.cc
@@ -55,37 +73,43 @@
 # these exceptions, look in the middle of the 'Makefile Machinery'
 # section. (grep/search for the file name)
 CXXFLAGS= \
-	-g -pipe -O2 -frename-registers -fomit-frame-pointer -ffast-math -fno-common \
+	-g -pipe -fno-inline \
+  -O2 -frename-registers -fomit-frame-pointer -ffast-math -fno-common \
 	-Wall -W -Wshadow -Wlarger-than-8192 -Wpointer-arith -Wcast-qual \
 	-Woverloaded-virtual -Weffc++ -Wdeprecated -Wnon-virtual-dtor \
-	-I"`pwd`" -I$(TEKKOTSU_ROOT) \
+	-I"`pwd`" -I$(TEKKOTSU_ROOT) -I$(TEKKOTSU_ROOT)/Motion/roboop -I$(TEKKOTSU_ROOT)/Shared/newmat \
 	-isystem $(TEKKOTSU_ROOT)/Shared/jpeg-6b \
 	-isystem $(OPENRSDK_ROOT)/OPEN_R/include/MCOOP \
 	-isystem $(OPENRSDK_ROOT)/OPEN_R/include/R4000 \
 	-isystem $(OPENRSDK_ROOT)/OPEN_R/include \
-	-DPLATFORM_APERIOS -DDEBUG -DOPENR_DEBUG -D$(TEKKOTSU_TARGET_MODEL) $(GLOBAL_MAP) \
+	-D$(TEKKOTSU_TARGET_PLATFORM) -DDEBUG -DOPENR_DEBUG -D$(TEKKOTSU_TARGET_MODEL) $(GLOBAL_MAP) \
 
-#Suggested additional flags
-# -ffast-math
+#These will be the actual build directories used for the current target
+TGT_BD:=$(TEKKOTSU_TARGET_PLATFORM)_$(TEKKOTSU_TARGET_MODEL)
+TK_BD:=$(TEKKOTSU_BUILDDIR)/$(TGT_BD)
+PROJ_BD:=$(PROJECT_BUILDDIR)/$(TGT_BD)
+$(shell mkdir -p $(TK_BD))
+$(shell mkdir -p $(PROJ_BD))
 
 
 ###################################################
 ##              SOURCE CODE LIST                 ##
 ###################################################
+
 # Find all of the source files: (except temp files in build directory)
 # You shouldn't need to change anything here unless you want to add
 # external libraries
-
-BUILDDIR=build
-$(shell mkdir -p $(BUILDDIR))
-$(shell mkdir -p $(TEKKOTSU_ROOT)/$(BUILDDIR))
 SRCSUFFIX=.cc
-PROJ_SRCS:=$(shell find . -name "*$(SRCSUFFIX)" \! -path "*/$(BUILDDIR)/*")
+PROJ_SRCS:=$(patsubst ./%,%,$(shell find . -name "*$(SRCSUFFIX)" -or -name "$(PROJECT_BUILDDIR)" \! -prune -or -name "templates" \! -prune))
+
 # We're assuming all of the source files we found are to be linked
 # into MMCombo.
 MAIN_SRCS:=$(PROJ_SRCS)
 
-USERLIBS:=$(TEKKOTSU_ROOT)/Shared/jpeg-6b/libjpeg.a
+# We can also link in third-party libraries
+USERLIBS:= $(TEKKOTSU_ROOT)/Shared/jpeg-6b/libjpeg.a \
+           $(TEKKOTSU_ROOT)/Motion/roboop/libroboop.a \
+           $(TEKKOTSU_ROOT)/Shared/newmat/libnewmat.a \
 
 
 ###################################################
@@ -103,9 +127,9 @@
 PROCESS_OBJS=MMCombo TinyFTPD SoundPlay
 MMCombo_COMP=MMCombo MMCombo/MMComboStub.o Behaviors Events Motion Shared SoundPlay/SoundManager.o SoundPlay/WAV.o Vision Wireless
 TinyFTPD_COMP=TinyFTPD TinyFTPD/TinyFTPDStub.o
-SoundPlay_COMP=SoundPlay SoundPlay/SoundPlayStub.o Shared/Config.o Shared/ProcessID.o Events/EventRouter.o Events/EventTranslator.o Events/EventBase.o Events/VisionObjectEvent.o Shared/LoadSave.o Shared/get_time.o
+SoundPlay_COMP=SoundPlay SoundPlay/SoundPlayStub.o Shared/Config.o Shared/ProcessID.o Events/EventRouter.o Events/EventTranslator.o Events/EventBase.o Events/LocomotionEvent.o Events/TextMsgEvent.o Events/VisionObjectEvent.o Shared/LoadSave.o Shared/get_time.o
 STUB_FILES:=$(addprefix $(TEKKOTSU_ROOT)/,$(addsuffix /stub.cfg,$(PROCESS_OBJS)))
-STUB_CHECK_FILES:=$(addprefix $(TEKKOTSU_ROOT)/$(BUILDDIR)/,$(subst /,-,$(STUB_FILES)))
+STUB_CHECK_FILES:=$(addprefix $(TK_BD)/,$(subst /,-,$(STUB_FILES)))
 
 # It's important that the process names and variables are the same
 # case as your memory stick reader - memsticks don't store case, and
@@ -117,11 +141,11 @@
 ifeq ($(FILENAME_CASE),lower)
 
 PROCESSES=mmcombo tinyftpd sndplay
-mmcombo_OBJS:=$(MAIN_SRCS:$(SRCSUFFIX)=.o) $(TEKKOTSU_ROOT)/$(BUILDDIR)/MMCombo.o
+mmcombo_OBJS:=$(addprefix $(PROJ_BD)/,$(MAIN_SRCS:$(SRCSUFFIX)=.o)) $(TK_BD)/MMCombo.o
 mmcombo_OCF:=$(TEKKOTSU_ROOT)/MMCombo/MMCombo.ocf
-tinyftpd_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/TinyFTPD.o
+tinyftpd_OBJS:=$(TK_BD)/TinyFTPD.o
 tinyftpd_OCF:=$(TEKKOTSU_ROOT)/TinyFTPD/TinyFTPD.ocf
-sndplay_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/SoundPlay.o
+sndplay_OBJS:=$(TK_BD)/SoundPlay.o
 sndplay_OCF:=$(TEKKOTSU_ROOT)/SoundPlay/SoundPlay.ocf
 CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makelowercase
 
@@ -135,11 +159,11 @@
 else
 
 PROCESSES=MMCOMBO TINYFTPD SNDPLAY
-MMCOMBO_OBJS:=$(MAIN_SRCS:$(SRCSUFFIX)=.o) $(TEKKOTSU_ROOT)/$(BUILDDIR)/MMCombo.o
+MMCOMBO_OBJS:=$(addprefix $(PROJ_BD)/,$(MAIN_SRCS:$(SRCSUFFIX)=.o)) $(TK_BD)/MMCombo.o
 MMCOMBO_OCF:=$(TEKKOTSU_ROOT)/MMCombo/MMCombo.ocf
-TINYFTPD_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/TinyFTPD.o
+TINYFTPD_OBJS:=$(TK_BD)/TinyFTPD.o
 TINYFTPD_OCF:=$(TEKKOTSU_ROOT)/TinyFTPD/TinyFTPD.ocf
-SNDPLAY_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/SoundPlay.o
+SNDPLAY_OBJS:=$(TK_BD)/SoundPlay.o
 SNDPLAY_OCF:=$(TEKKOTSU_ROOT)/SoundPlay/SoundPlay.ocf
 CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makeuppercase
 
@@ -153,30 +177,29 @@
 endif
 
 # creates process build target names: MMCombo -> build/MMCombo.o
-BUILDS:=$(foreach proc,$(PROCESS_OBJS),$(TEKKOTSU_ROOT)/$(BUILDDIR)/$(proc).o)
+BUILDS:=$(foreach proc,$(PROCESS_OBJS),$(TK_BD)/$(proc).o)
 
 # Each process build target depends on the component object files that
-# should be linked together.  These live in the
-# $TEKKOTSU_ROOT/$BUILDDIR directory and should be fairly static
-# unless you're editing the framework itself.  The automatic way of
-# creating these dependancies automatically is too messy, just add a
-# rule for each process by hand: (skip lines!)
-$(word 1,$(BUILDS)): $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$($(word 1,$(PROCESS_OBJS))_COMP)), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc") )))
+# should be linked together.  These live in the $TK_BD directory and
+# should be fairly static unless you're editing the framework itself.
+# The automatic way of creating these dependancies automatically is
+# too messy, just add a rule for each process by hand: (skip lines!)
+$(word 1,$(BUILDS)): $(foreach comp,$($(word 1,$(PROCESS_OBJS))_COMP), $(if $(suffix $(comp)),$(TK_BD)/$(comp),$(patsubst $(TEKKOTSU_ROOT)%.cc,$(TK_BD)%.o,$(shell find $(TEKKOTSU_ROOT)/$(comp) -name "*.cc") )))
 
-$(word 2,$(BUILDS)): $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$($(word 2,$(PROCESS_OBJS))_COMP)), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc") )))
+$(word 2,$(BUILDS)): $(foreach comp,$($(word 2,$(PROCESS_OBJS))_COMP), $(if $(suffix $(comp)),$(TK_BD)/$(comp),$(patsubst $(TEKKOTSU_ROOT)%.cc,$(TK_BD)%.o,$(shell find $(TEKKOTSU_ROOT)/$(comp) -name "*.cc") )))
 
-$(word 3,$(BUILDS)): $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$($(word 3,$(PROCESS_OBJS))_COMP)), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc") )))
+$(word 3,$(BUILDS)): $(foreach comp,$($(word 3,$(PROCESS_OBJS))_COMP), $(if $(suffix $(comp)),$(TK_BD)/$(comp),$(patsubst $(TEKKOTSU_ROOT)%.cc,$(TK_BD)%.o,$(shell find $(TEKKOTSU_ROOT)/$(comp) -name "*.cc") )))
 
 # Each of the executable binaries depends on the corresponding
 # framework build target(s) plus any project files which were
 # specified above. (by default, all project files are linked into
-# MMCombo) These live in the project directory's $BUILDDIR and will
+# MMCombo) These live in the project directory's build dir and will
 # need to be recompiled any time you change source that's part of that
 # process (but not otherwise ;)
 # Again, the automatic way of creating these dependancies
 # automatically is too messy, just add a rule for each process by
 # hand: (skip lines!)
-PROC_BINS:=$(addprefix $(BUILDDIR)/,$(addsuffix $(BINSUFFIX),$(PROCESSES)))
+PROC_BINS:=$(addprefix $(PROJ_BD)/,$(addsuffix $(BINSUFFIX),$(PROCESSES)))
 
 $(word 1,$(PROC_BINS)): $($(word 1,$(PROCESSES))_OBJS) $($(word 1,$(PROCESSES))_OCF)
 
@@ -201,77 +224,93 @@
 # list of all source files of all components, sorted to remove
 # duplicates.  This gives us all the source files which we care about,
 # all in one place.
-SRCS:=$(sort $(foreach comp,$(COMPONENTS), $(if $(suffix $(filter-out %.a,$(comp))),$(TEKKOTSU_ROOT)/$(basename $(comp)).cc,$(shell find $(TEKKOTSU_ROOT)/$(comp) -name "*.cc") ))) $(MAIN_SRCS)
-OBJS:=$(SRCS:$(SRCSUFFIX)=.o)
-DEPENDS:=$(SRCS:$(SRCSUFFIX)=.d)
+TK_SRCS:=$(sort $(foreach comp,$(COMPONENTS), $(if $(suffix $(filter-out %.a,$(comp))),$(TEKKOTSU_ROOT)/$(basename $(comp)).cc,$(shell find $(TEKKOTSU_ROOT)/$(comp) -name "*.cc") )))
+TK_DEPENDS:=$(subst $(TEKKOTSU_ROOT),$(TK_BD),$(TK_SRCS:$(SRCSUFFIX)=.d))
+PROJ_DEPENDS:=$(addprefix $(PROJ_BD)/,$(PROJ_SRCS:$(SRCSUFFIX)=.d))
+DEPENDS:=$(sort $(PROJ_DEPENDS) $(TK_DEPENDS))
 
 # These are the file names of the final executable binaries, in the
 # memstick image directory
-INSTALL_BINS:=$(addprefix $(INSTALLDIR)/,$(addsuffix $(BINSUFFIX),$(PROCESSES)))
+INSTALL_BINS:=$(addprefix $(INSTALLDIR)/,$(MAINFORK) $(MOTOFORK) $(addsuffix $(BINSUFFIX),$(filter-out mmcombo MMCOMBO,$(PROCESSES))))
 
 CXX=$(OPENRSDK_ROOT)/bin/mipsel-linux-g++
 LD=$(OPENRSDK_ROOT)/bin/mipsel-linux-ld
 STRIP=$(OPENRSDK_ROOT)/bin/mipsel-linux-strip
 MKBIN=$(OPENRSDK_ROOT)/OPEN_R/bin/mkbin
 STUBGEN=$(OPENRSDK_ROOT)/OPEN_R/bin/stubgen2
-COLORFILT=${TEKKOTSU_ROOT}/tools/colorfilt
+COLORFILT=$(TEKKOTSU_ROOT)/tools/colorfilt
 FILTERSYSWARN=$(TEKKOTSU_ROOT)/tools/filtersyswarn/filtersyswarn $(OPENRSDK_ROOT)
 MKBINFLAGS=-p $(OPENRSDK_ROOT)
 
-.PHONY: all compile install clean cleanDeps cleanProj cleanTemps Tekkotsu reportTarget newstick update $(INSTALLDIR)/$(MMCOMBOBIN) docs dox doc cleandoc updateTools
+.PHONY: all compile install clean cleanDeps cleanProj cleanTemps Tekkotsu reportTarget newstick update docs dox doc cleandoc updateTools checkInstalledTimestamp
 
 all: compile
 	@echo "Build successful."
 	@echo "Type: '$(MAKE) install' to copy all files to the memory stick"
 	@echo "  or: '$(MAKE) update' to copy only changed files"
+	@echo "  or: '$(TEKKOTSU_ROOT)/tools/{ftpinstall,ftpupdate} <ipaddr> ms' might also be useful"
 
-#the touch at the end is because memsticks seem to round time to even seconds, which screws up updates.  Grr.
 reportTarget:
 	@echo " ** Targeting $(TEKKOTSU_TARGET_MODEL) for build ** ";
 
 updateTools:
 	cd $(TEKKOTSU_ROOT)/tools && $(MAKE);
 
-compile: reportTarget cleanTemps updateTools $(USERLIBS) $(INSTALL_BINS)
-	@image="$(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))" ; \
+updateLibs:
+	@echo "Updating libraries..."
+	@$(foreach x,$(USERLIBS),make -C $(dir $(x)) $(notdir $(x)) && ) true
+
+#the touch at the end is because memsticks seem to round time to even seconds, which screws up updates.  Grr.
+compile: reportTarget cleanTemps updateTools updateLibs checkInstalledTimestamp $(PROJ_BD)/installed.timestamp
+	@image="$(PROJ_BD)/$(notdir $(MEMSTICK_ROOT))" ; \
 	if [ "$(TEKKOTSU_ROOT)/TARGET_MODEL" -nt "$$image" ] ; then \
 		echo "Deleting old cached OPEN-R binaries"; \
 		rm -rf "$$image" ; \
 	fi; \
 	if [ \! -d "$$image" ] ; then \
 		if [ \! -d "$(SYSTEM_BINARIES)" ] ; then \
-			echo "Could not find OPEN-R system binaries" ; \
+v			echo "Could not find OPEN-R system binaries" ; \
 			exit 1 ; \
 		fi ; \
 		echo "Copying system files..." ; \
 		cp -r "$(SYSTEM_BINARIES)" "$$image" ; \
 		chmod -R u+w "$$image" ; \
-		(cd "$$image" && $(CONVERTCASE) -r . ); \
+		cur=`pwd`; \
+		cd "$$image"; \
+		$(CONVERTCASE) -r *; \
+		cd "$$cur"; \
 		rm -f "$$image/open-r/mw/conf/connect.cfg" "$$image/open-r/mw/conf/object.cfg" "$$image/open-r/system/conf/wlandflt.txt" ; \
 		curt=`date +%Y%m%d%H%M`; \
 		find "$$image" -exec touch -ft $$curt \{\} \; ; \
-	fi
+	fi;
 
+checkInstalledTimestamp:
+	@for x in $(INSTALL_BINS) ; do \
+		if [ "$$x" -nt "$(PROJ_BD)/installed.timestamp" ] ; then \
+			printf "Target switch detected, cleaning binaries..." ; \
+			rm -f $(INSTALL_BINS) ; \
+			printf "done.\n" ; \
+		fi; \
+	done;
 
-ifneq ($(MAKECMDGOALS),clean)
-ifneq ($(MAKECMDGOALS),cleanProj)
-ifneq ($(MAKECMDGOALS),cleanTemps)
-ifneq ($(MAKECMDGOALS),cleanDeps)
+ifeq ($(findstring clean,$(MAKECMDGOALS)),)
+ifeq ($(findstring docs,$(MAKECMDGOALS)),)
 -include $(DEPENDS)
 endif
 endif
-endif
-endif
 
 $(STUB_CHECK_FILES):
 	@thedir=`echo $@ | sed 's/.*-\(.*\)-.*/\1/g'`; \
 	cd $(TEKKOTSU_ROOT)/$$thedir ; \
 	$(STUBGEN) stub.cfg ; \
+	mkdir -p $(dir $@) ; \
 	touch $@ ;
 
-%.d : $(STUB_CHECK_FILES) %$(SRCSUFFIX)
-	@echo Building $@...
-	@$(CXX) $(CXXFLAGS) -MP -MG -MT $@ -MT $*.o -MM $*$(SRCSUFFIX) > $@
+%.d : $(STUB_CHECK_FILES)
+	@mkdir -p $(dir $@)
+	@src=$(patsubst %.d,%.cc,$(if $(findstring $(TK_BD),$@),$(patsubst $(TK_BD)%,$(TEKKOTSU_ROOT)%,$@),$(patsubst $(PROJ_BD)/%,%,$@))); \
+	echo "$@..." | sed 's@.*$(TGT_BD)/@Generating @'; \
+	$(CXX) $(CXXFLAGS) -MP -MG -MT "$@" -MT "$(@:.d=.o)" -MM "$$src" > $@
 
 %/def.h %/entry.h: %/stub.cfg
 	@echo "Doing $@"
@@ -286,7 +325,7 @@
 	cd $(dir $@) && $(STUBGEN) stub.cfg
 	@echo "Done with $@"
 
-#%Stub.cc: 
+#%Stub.cc:
 #	cd $(dir $@) && $(STUBGEN) stub.cfg
 #	@echo "Done with $@"
 
@@ -302,106 +341,115 @@
 	@find . -name "*.cc" -exec grep -H "$(notdir $@)" \{\} \; ;
 	@find $(TEKKOTSU_ROOT) -name "*.h" -exec grep -H "$(notdir $@)" \{\} \; ;
 	@find $(TEKKOTSU_ROOT) -name "*.cc" -exec grep -H "$(notdir $@)" \{\} \; ;
-	@echo "You might need to remove all the .d files (make cleanDeps) to get rid of this error.";
+	@echo "";
+	@echo "You might need to rebuild the dependancy files ('make cleanDeps') to get rid of this error.";
 	@exit 1
 
 #The "fork" we do of MMCombo into MainObj and MotoObj crashes with optimization... not a big loss, just turn it off for these files
-$(TEKKOTSU_ROOT)/MMCombo/MMCombo.o $(TEKKOTSU_ROOT)/MMCombo/MMComboStub.o: %.o: %$(SRCSUFFIX) $(FILTERSYSWARN)  $(TEKKOTSU_ROOT)/TARGET_MODEL
-	@if [ -r dist_hosts.txt ] ; then \
+$(TK_BD)/MMCombo/MMCombo.o $(TK_BD)/MMCombo/MMComboStub.o: %.o:
+	@mkdir -p $(dir $@)
+	@src=$(patsubst %.o,%$(SRCSUFFIX),$(if $(findstring $(TK_BD),$@),$(patsubst $(TK_BD)%,$(TEKKOTSU_ROOT)%,$@),$(patsubst $(PROJ_BD)/%,%,$@))); \
+	if [ -r dist_hosts.txt ] ; then \
 		echo "Adding $@ to job list"; \
-		echo "$(CXX) $(filter-out -O2,$(CXXFLAGS)) -o $@ -c $< > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(BUILDDIR)/joblist.txt ; \
+		echo "$(CXX) $(filter-out -O2,$(CXXFLAGS)) -o $@ -c $$src > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(PROJ_BD)/joblist.txt ; \
 		touch $@; \
-		echo "$@" >> $(BUILDDIR)/touched.txt ; \
+		echo "$@" >> $(PROJ_BD)/touched.txt ; \
 	else \
-		echo "Compiling $<... (no -O2)"; \
-		$(CXX) $(filter-out -O2,$(CXXFLAGS)) -o $@ -c $< > $*.log 2>&1; \
+		echo "Compiling $$src... (no -O2)"; \
+		$(CXX) $(filter-out -O2,$(CXXFLAGS)) -o $@ -c $$src > $*.log 2>&1; \
 		retval=$$?; \
-		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT) | $(TEKKOTSU_LOGVIEW); \
 		test $$retval -eq 0; \
 	fi;
 
-$(TEKKOTSU_ROOT)/TinyFTPD/TinyFTPD.o $(TEKKOTSU_ROOT)/TinyFTPD/FtpMethod.o $(TEKKOTSU_ROOT)/TinyFTPD/FtpRequest.o $(TEKKOTSU_ROOT)/TinyFTPD/FtpDTP.o $(TEKKOTSU_ROOT)/TinyFTPD/FtpPI.o: %.o: %$(SRCSUFFIX) $(FILTERSYSWARN) $(TEKKOTSU_ROOT)/TARGET_MODEL
-	@if [ -r dist_hosts.txt ] ; then \
+$(TK_BD)/TinyFTPD/TinyFTPD.o $(TK_BD)/TinyFTPD/FtpMethod.o $(TK_BD)/TinyFTPD/FtpRequest.o $(TK_BD)/TinyFTPD/FtpDTP.o $(TK_BD)/TinyFTPD/FtpPI.o: %.o:
+	@mkdir -p $(dir $@)
+	@src=$(patsubst %.o,%$(SRCSUFFIX),$(if $(findstring $(TK_BD),$@),$(patsubst $(TK_BD)%,$(TEKKOTSU_ROOT)%,$@),$(patsubst $(PROJ_BD)/%,%,$@))); \
+	if [ -r dist_hosts.txt ] ; then \
 		echo "Adding $@ to job list"; \
-		echo "$(CXX) $(filter-out -DOPENR_DEBUG,$(filter-out -Weffc++,$(CXXFLAGS))) -o $@ -c $< > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(BUILDDIR)/joblist.txt ; \
+		echo "$(CXX) $(filter-out -DOPENR_DEBUG,$(filter-out -Weffc++,$(CXXFLAGS))) -o $@ -c $$src > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(PROJ_BD)/joblist.txt ; \
 		touch $@; \
-		echo "$@" >> $(BUILDDIR)/touched.txt ; \
+		echo "$@" >> $(PROJ_BD)/touched.txt ; \
 	else \
-		echo "Compiling $<... (reduced warnings, no OPENR_DEBUG)"; \
-		$(CXX) $(filter-out -DOPENR_DEBUG,$(filter-out -Weffc++,$(CXXFLAGS))) -o $@ -c $< > $*.log 2>&1; \
+		echo "Compiling $$src... (reduced warnings, no OPENR_DEBUG)"; \
+		$(CXX) $(filter-out -DOPENR_DEBUG,$(filter-out -Weffc++,$(CXXFLAGS))) -o $@ -c $$src > $*.log 2>&1; \
 		retval=$$?; \
-		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT) | $(TEKKOTSU_LOGVIEW); \
 		test $$retval -eq 0; \
 	fi;
 
-$(TEKKOTSU_ROOT)/SoundPlay/WAV.o $(TEKKOTSU_ROOT)/Vision/Vision.o: %.o: %$(SRCSUFFIX) $(FILTERSYSWARN) $(TEKKOTSU_ROOT)/TARGET_MODEL
-	@if [ -r dist_hosts.txt ] ; then \
+$(TK_BD)/SoundPlay/WAV.o: %.o: $(FILTERSYSWARN)
+	@mkdir -p $(dir $@)
+	@src=$(patsubst %.o,%$(SRCSUFFIX),$(if $(findstring $(TK_BD),$@),$(patsubst $(TK_BD)%,$(TEKKOTSU_ROOT)%,$@),$(patsubst $(PROJ_BD)/%,%,$@))); \
+	if [ -r dist_hosts.txt ] ; then \
 		echo "Adding $@ to job list"; \
-		echo "$(CXX) $(filter-out -Weffc++,$(CXXFLAGS)) -o $@ -c $< > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(BUILDDIR)/joblist.txt ; \
+		echo "$(CXX) $(filter-out -Weffc++,$(CXXFLAGS)) -o $@ -c $$src > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(PROJ_BD)/joblist.txt ; \
 		touch $@; \
-		echo "$@" >> $(BUILDDIR)/touched.txt ; \
+		echo "$@" >> $(PROJ_BD)/touched.txt ; \
 	else \
-		echo "Compiling $<... (reduced warnings)"; \
-		$(CXX) $(filter-out -Weffc++,$(CXXFLAGS)) -o $@ -c $< > $*.log 2>&1; \
+		echo "Compiling $$src... (reduced warnings)"; \
+		$(CXX) $(filter-out -Weffc++,$(CXXFLAGS)) -o $@ -c $$src > $*.log 2>&1; \
 		retval=$$?; \
-		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT) | $(TEKKOTSU_LOGVIEW); \
 		test $$retval -eq 0; \
 	fi;
 
-%.o: %$(SRCSUFFIX) $(FILTERSYSWARN) $(TEKKOTSU_ROOT)/TARGET_MODEL
-	@if [ -r dist_hosts.txt ] ; then \
+%.o:
+	@mkdir -p $(dir $@)
+	@src=$(patsubst %.o,%$(SRCSUFFIX),$(if $(findstring $(TK_BD),$@),$(patsubst $(TK_BD)%,$(TEKKOTSU_ROOT)%,$@),$(patsubst $(PROJ_BD)/%,%,$@))); \
+	if [ -r dist_hosts.txt ] ; then \
 		echo "Adding $@ to job list"; \
-		echo "$(CXX) $(CXXFLAGS) -o $@ -c $< > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(BUILDDIR)/joblist.txt ; \
+		echo "$(CXX) $(CXXFLAGS) -o $@ -c $$src > $*.log 2>&1; retval=\$$?; cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); test \$$retval -eq 0;" >> $(PROJ_BD)/joblist.txt ; \
 		touch $@; \
-		echo "$@" >> $(BUILDDIR)/touched.txt ; \
+		echo "$@" >> $(PROJ_BD)/touched.txt ; \
 	else \
-		echo "Compiling $<..."; \
-		$(CXX) $(CXXFLAGS) -o $@ -c $< > $*.log 2>&1; \
+		echo "Compiling $$src..."; \
+		$(CXX) $(CXXFLAGS) -o $@ -c $$src > $*.log 2>&1; \
 		retval=$$?; \
-		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT); \
+		cat $*.log | $(FILTERSYSWARN) | $(COLORFILT) | $(TEKKOTSU_LOGVIEW); \
 		test $$retval -eq 0; \
 	fi;
 
 #This is for external libraries which we are including, such as libjpeg
 %.a:
+	export OPENRSDK_ROOT=$(OPENRSDK_ROOT) ;\
+	export TEKKOTSU_ROOT=$(TEKKOTSU_ROOT) ;\
 	$(MAKE) -C $(dir $@) $(notdir $@)
 
-$(TEKKOTSU_ROOT)/TARGET_MODEL:
-	$(error Could not find $(TEKKOTSU_ROOT)/TARGET_MODEL)
-
 #BUILDS:   (framework object files, one per process - resides in framework)
 $(BUILDS):
-	@if [ -r dist_hosts.txt -a -r $(BUILDDIR)/joblist.txt ] ; then \
+	@if [ -r dist_hosts.txt -a -r $(PROJ_BD)/joblist.txt ] ; then \
 		echo "Distributing compiles..."; \
-		../tools/pm.pl dist_hosts.txt $(BUILDDIR)/joblist.txt ; \
+		../tools/pm.pl dist_hosts.txt $(PROJ_BD)/joblist.txt ; \
 	fi
-	@rm -f $(BUILDDIR)/joblist.txt; #this is so we don't rebuild multiple times
+	@rm -f $(PROJ_BD)/joblist.txt; #this is so we don't rebuild multiple times
 	@echo "Linking component object files..."
-	@if [ $(words $(sort $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$($(basename $(notdir $@))_COMP)), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc")))))) -gt 20 ] ; then \
+	@if [ $(words $(foreach comp,$(addprefix $(TK_BD)/,$($(basename $(notdir $@))_COMP)),$(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.o"))))) -gt 20 ] ; then \
 		echo "$@ <- [...]"; \
 	else \
-		echo "$@ <- $(sort $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$(filter-out %.a,$($(basename $(notdir $@))_COMP))), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc") ))))"; \
+		echo "$@ <- $(sort $(foreach comp,$(addprefix $(TK_BD)/,$(filter-out %.a,$($(basename $(notdir $@))_COMP))), $(if $(suffix $(comp)),$(comp),$(shell find $(comp) -name "*.o") )))" | sed 's@$(TK_BD)/@@g'; \
 	fi;
-	@$(LD) -i $(sort $(foreach comp,$(addprefix $(TEKKOTSU_ROOT)/,$(filter-out %.a,$($(basename $(notdir $@))_COMP))), $(if $(suffix $(comp)),$(comp),$(patsubst %.cc,%.o,$(shell find $(comp) -name "*.cc") )))) -o $@ ; \
+	@$(LD) -i     $(sort $(foreach comp,$(addprefix $(TK_BD)/,$(filter-out %.a,$($(basename $(notdir $@))_COMP))), $(if $(suffix $(comp)),$(comp),$(shell find $(comp) -name "*.o") ))) -o $@ ; \
 		if [ $$? -ne 0 ] ; then exit 1; fi;
 
-
 #PROC_BINS:    (executable binaries, uncompressed)
 # we have to do a couple extra steps to cd into the builddir because
 # mkbin doesn't support -o target in a different directory... drops an
 # intermediate file in . and then complains (as of 1.1.3 anyway)
-$(BUILDDIR)/%$(BINSUFFIX): $(USERLIBS)
-	@if [ -r dist_hosts.txt -a -r $(BUILDDIR)/joblist.txt ] ; then \
+$(PROJ_BD)/%$(BINSUFFIX): $(USERLIBS)
+	@if [ -r dist_hosts.txt -a -r $(PROJ_BD)/joblist.txt ] ; then \
 		echo "Distributing compiles..."; \
-		../tools/pm.pl dist_hosts.txt $(BUILDDIR)/joblist.txt ; \
+		../tools/pm.pl dist_hosts.txt $(PROJ_BD)/joblist.txt ; \
 	fi
-	@rm -f $(BUILDDIR)/joblist.txt; #this is so we don't rebuild multiple times
+	@rm -f $(PROJ_BD)/joblist.txt; #this is so we don't rebuild multiple times
 	@echo "Creating executable binary..."
-	@echo "$@ <- $($(basename $(notdir $@))_OBJS), $($(basename $(notdir $@))_OCF), $(LIBS) $(USERLIBS)"; #we'll need to do some filtering on USERLIBS below because now we're in builddir
-	@$(LD) -i $($(basename $(notdir $@))_OBJS) -o $(BUILDDIR)/tmp.o
-	@cp $($(basename $(notdir $@))_OCF) $(BUILDDIR)/tmp.ocf
-	@cd $(BUILDDIR) ; \
-	$(MKBIN) $(MKBINFLAGS) -o $(notdir $@) tmp.o -m tmp.ocf $(LIBS) $(filter /%,$(USERLIBS)) $(addprefix ../,$(filter-out /%,$(USERLIBS))) ; \
+	@echo "$@ <- $($(basename $(notdir $@))_OBJS), $($(basename $(notdir $@))_OCF), $(LIBS) $(USERLIBS)" | sed 's@ $(PROJ_BD)/@ @g';
+	@#we'll need to do some filtering on USERLIBS below because now we'll be in builddir below
+	@$(LD) -i $($(basename $(notdir $@))_OBJS) -o $(PROJ_BD)/tmp.o
+	@cp $($(basename $(notdir $@))_OCF) $(PROJ_BD)/tmp.ocf
+	@pt=`pwd`;\
+	cd $(PROJ_BD) ; \
+	$(MKBIN) $(MKBINFLAGS) -o $(notdir $@) tmp.o -m tmp.ocf $(LIBS) $(filter /%,$(USERLIBS)) $(addsuffix \",$(addprefix \"$$pt/,$(filter-out /%,$(USERLIBS)))) ; \
 	if [ $$? -gt 0 ] ; then \
 		echo "Build failed."; \
 		exit 1; \
@@ -411,47 +459,48 @@
 
 
 #INSTALL_BINS:     (compressed executables, in proper location in image directory)
-$(INSTALLDIR)/%$(BINSUFFIX): $(BUILDDIR)/%$(BINSUFFIX)
+$(INSTALLDIR)/%$(BINSUFFIX): $(PROJ_BD)/%$(BINSUFFIX)
 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
-		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+		echo "I can't find $(INSTALLDIR).  Hmmm."; \
 		exit 1; \
 	fi;
 	@echo "Compressing $< -> $@"
 	@gzip -c $< > $@;
 
-$(INSTALLDIR)/$(MMCOMBOBIN): $(INSTALLDIR)/$(MAINFORK) $(INSTALLDIR)/$(MOTOFORK)
-
-$(INSTALLDIR)/$(MAINFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
+$(INSTALLDIR)/$(MAINFORK): $(PROJ_BD)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
-		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+		echo "I can't find $(INSTALLDIR).  Hmmm."; \
 		exit 1; \
 	fi;
 	@echo "Compressing $< ~> $@"
 	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MainObj | gzip -c > $@
 #	@sed 's/MMCombo/MainObj/g;s/mmcombo/mainobj/g' $< | gzip -c > $@
 
-$(INSTALLDIR)/$(MOTOFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
+$(INSTALLDIR)/$(MOTOFORK): $(PROJ_BD)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
-		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+		echo "I can't find $(INSTALLDIR).  Hmmm."; \
 		exit 1; \
 	fi;
 	@echo "Compressing $< ~> $@"
 	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MotoObj | gzip -c > $@
 #	@sed 's/MMCombo/MotoObj/g;s/mmcombo/motoobj/g' $< | gzip -c > $@
 
+$(PROJ_BD)/installed.timestamp: $(INSTALL_BINS)
+	@touch $@
+
 install: compile
 	@echo "Installing files to memory stick at $(MEMSTICK_ROOT)"
 	@$(TEKKOTSU_ROOT)/tools/cpymem --all --img $(MSIMGDIR) --tgt $(MEMSTICK_ROOT) --tools $(TEKKOTSU_ROOT)/tools
 
 update: compile $(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime
 	@echo "Syncing $(MSIMGDIR) and $(MEMSTICK_ROOT)"
-	@$(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime `find $(MSIMGDIR)`
+	@$(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime `find $(MSIMGDIR)` $(PROJ_BD)/installed.timestamp
 	@$(TEKKOTSU_ROOT)/tools/mntmem $(MEMSTICK_ROOT)
 	@if [ $(STRICT_MEMSTICK_IMAGE) ] ; then \
 		echo "Strict image copy is on." ; \
-		rsync -rLtWCv --delete $(MSIMGDIR)/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
+		rsync -rLtWCv --delete $(MSIMGDIR)/* $(PROJ_BD)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
 	else \
-		rsync -rLtWCv $(MSIMGDIR)/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
+		rsync -rLtWCv $(MSIMGDIR)/* $(PROJ_BD)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
 	fi;
 	@$(TEKKOTSU_ROOT)/tools/umntmem $(MEMSTICK_ROOT)
 
@@ -465,16 +514,16 @@
 	(cd $(TEKKOTSU_ROOT)/tools && $(MAKE));
 
 cleanTemps:
-	rm -f $(BUILDDIR)/joblist.txt $(BUILDDIR)/touched.txt
+	rm -f $(PROJ_BD)/joblist.txt $(PROJ_BD)/touched.txt
 
 clean: cleanProj
-	@printf "Cleaning all .o, .d, .log and ~ files corresponding to .cc files..."
-	@rm -f $(OBJS) $(DEPENDS) $(SRCS:$(SRCSUFFIX)=.log) $(addsuffix ~,$(SRCS)) $(SRCS:$(SRCSUFFIX)=.h~)
+	@printf "Cleaning all ~ files corresponding to .cc files..."
+	@rm -f $(addsuffix ~,$(TK_SRCS)) $(TK_SRCS:$(SRCSUFFIX)=.h~)
 	@printf "done.\n"
 	rm -f $(foreach proc,$(PROCESS_OBJS),$(TEKKOTSU_ROOT)/$(proc)/$(proc)Stub.cc $(TEKKOTSU_ROOT)/$(proc)/$(proc)Stub.h $(TEKKOTSU_ROOT)/$(proc)/def.h $(TEKKOTSU_ROOT)/$(proc)/entry.h)
-	rm -rf $(TEKKOTSU_ROOT)/$(BUILDDIR)
+	rm -rf $(TEKKOTSU_BUILDDIR)
 	cd $(TEKKOTSU_ROOT)/tools ; $(MAKE) clean
-	$(foreach lib,$(USERLIBS),$(MAKE) -C $(dir $(lib)) clean)
+	$(foreach lib,$(USERLIBS),$(MAKE) -C $(dir $(lib)) clean ;)
 
 cleanDeps:
 	@printf "Cleaning all .d files corresponding to .cc files..."
@@ -482,14 +531,11 @@
 	@printf "done.\n"
 
 cleanProj:
-	@printf "Cleaning all .o, .d, .log and ~ files corresponding to project .cc files..."
-	@rm -f $(PROJ_SRCS:$(SRCSUFFIX)=.o)
-	@rm -f $(PROJ_SRCS:$(SRCSUFFIX)=.d)
-	@rm -f $(PROJ_SRCS:$(SRCSUFFIX)=.log)
+	@printf "Cleaning all ~ files corresponding to project .cc files..."
 	@rm -f $(addsuffix ~,$(PROJ_SRCS)) $(PROJ_SRCS:$(SRCSUFFIX)=.h~)
 	@printf "done.\n"
-	rm -rf $(BUILDDIR)
-	rm -f $(INSTALL_BINS) $(INSTALLDIR)/$(MAINFORK) $(INSTALLDIR)/$(MOTOFORK)
+	rm -rf $(PROJECT_BUILDDIR)
+	rm -f $(INSTALL_BINS)
 
 dox doc docs:
 	cd $(TEKKOTSU_ROOT) && $(MAKE) $@
Index: project/StartupBehavior.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior.cc,v
retrieving revision 1.59
retrieving revision 1.64
diff -u -d -r1.59 -r1.64
--- project/StartupBehavior.cc	18 Feb 2004 21:13:48 -0000	1.59
+++ project/StartupBehavior.cc	18 Oct 2004 17:01:38 -0000	1.64
@@ -3,7 +3,6 @@
 #include "Behaviors/Controller.h"
 #include "Behaviors/Controls/BatteryCheckControl.h"
 #include "Behaviors/Controls/ControlBase.h"
-#include "Behaviors/Controls/PostureEditor.h"
 #include "Behaviors/Controls/HelpControl.h"
 #include "Behaviors/Controls/RebootControl.h"
 #include "Behaviors/Controls/ShutdownControl.h"
@@ -42,7 +41,7 @@
 
 	//This will "fade" in the PIDs so the joints don't jerk to full
 	//power, also looks cooler
-	pid_id=motman->addMotion(SharedObject<PIDMC>(0),MotionManager::kEmergencyPriority+2,false);
+	pid_id=motman->addPersistentMotion(SharedObject<PIDMC>(0),MotionManager::kEmergencyPriority+2);
 	//also, pause before we start fading in, PIDs take effect right
 	//away, before the emergencystop is picked up
 	erouter->addTimer(this,0,4*FrameTime*NumFrames,true);
@@ -54,13 +53,13 @@
 	//Note that if you don't want to start in estop, you should then
 	//also uncomment the line at the end of this function
 	stop->setStopped(true,false); 
-	stop_id=motman->addMotion(stop,MotionManager::kEmergencyPriority);
+	stop_id=motman->addPersistentMotion(stop,MotionManager::kEmergencyPriority);
 	
 	//This displays the current battery conditions on the console
 	BatteryCheckControl batchk;
+	//	const SharedObject<LedMC> led;
+	//	batchk.activate(motman->addPrunableMotion(led,MotionManager::kEmergencyPriority+1),NULL);
 	batchk.activate(MotionManager::invalid_MC_ID,NULL);
-	//	const SharedObject<LedMC> led; //! @todo LedMC's don't support autopruning yet, it should for uses like this
-	//	batchk.activate(motman->addMotion(led,true));
 	batchk.deactivate();
 
 	//This is what runs the menu system
@@ -86,7 +85,7 @@
 		closeMouth->setOutputCmd(mouthOffset,outputRanges[mouthOffset][MaxRange]);
 		closeMouth->setPlayTime(3500); //and hold it for another .5 seconds
 		closeMouth->setOutputCmd(mouthOffset,outputRanges[mouthOffset][MaxRange]);
-		motman->addMotion(closeMouth,MotionManager::kEmergencyPriority+1,true);
+		motman->addPrunableMotion(closeMouth,MotionManager::kEmergencyPriority+1);
 		erouter->addTimer(this,1,3250,false);
 	}
 
@@ -157,8 +156,6 @@
 		SetupTekkotsuMon();
 		SetupStatusReports();
 		SetupFileAccess();
-		SetupWalkEdit();
-		addItem(new PostureEditor());
 		SetupVision();
 		addItem(new ControlBase("Shutdown?","Confirms decision to reboot or shut down"));
 		startSubMenu();
Index: project/StartupBehavior_SetupBackgroundBehaviors.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupBackgroundBehaviors.cc,v
retrieving revision 1.8
retrieving revision 1.13
diff -u -d -r1.8 -r1.13
--- project/StartupBehavior_SetupBackgroundBehaviors.cc	19 Jan 2004 08:03:22 -0000	1.8
+++ project/StartupBehavior_SetupBackgroundBehaviors.cc	18 Oct 2004 23:53:37 -0000	1.13
@@ -3,15 +3,19 @@
 #include "Behaviors/Controls/ControlBase.h"
 #include "Behaviors/Controls/BehaviorSwitchControl.h"
 
+#include "Behaviors/Demos/SimpleChaseBallBehavior.h"
+#include "Behaviors/Demos/StareAtBallBehavior.h"
 #include "Behaviors/Demos/AutoGetupBehavior.h"
 #include "Behaviors/Demos/BatteryMonitorBehavior.h"
 #include "Behaviors/Demos/HeadLevelBehavior.h"
 #include "Behaviors/Demos/ToggleHeadLightBehavior.h"
-#include "Behaviors/Demos/HelloWorldBehavior.h"
 #include "Behaviors/Demos/CrashTestBehavior.h"
+#include "Behaviors/Demos/FreezeTestBehavior.h"
 #include "Behaviors/Demos/RelaxBehavior.h"
 #include "Behaviors/Demos/WorldStateVelDaemon.h"
 #include "Behaviors/Demos/CameraBehavior.h"
+#include "Behaviors/Demos/MotionStressTestBehavior.h"
+#include "Behaviors/Demos/ASCIIVisionBehavior.h"
 
 #include "Shared/WorldState.h"
 #include "Shared/ERS210Info.h"
@@ -21,16 +25,30 @@
 	addItem(new ControlBase("Background Behaviors","Background daemons and monitors"));
 	startSubMenu();
 	{ 
-		addItem((new BehaviorSwitchControl<AutoGetupBehavior>("AutoGetupBehavior",false))->start());
-		addItem((new BehaviorSwitchControl<BatteryMonitorBehavior>("BatteryMonitorBehavior",false))->start());
+		addItem(new BehaviorSwitchControl<SimpleChaseBallBehavior>("SimpleChaseBallBehavior",false));
+		addItem(new BehaviorSwitchControl<StareAtBallBehavior>("StareAtBallBehavior",false));
 		addItem(new BehaviorSwitchControl<HeadLevelBehavior>("HeadLevelBehavior",false));
 		if(state->robotDesign & WorldState::ERS220Mask)
 			addItem(new BehaviorSwitchControl<ToggleHeadLightBehavior>("ToggleHeadLightBehavior",false));
-		addItem(new BehaviorSwitchControl<HelloWorldBehavior>("HelloWorldBehavior",false));
-		addItem(new BehaviorSwitchControl<CrashTestBehavior>("CrashTestBehavior",false));
 		addItem(new BehaviorSwitchControl<RelaxBehavior>("RelaxBehavior",false));
 		addItem(new BehaviorSwitchControl<CameraBehavior>("CameraBehavior",false));
-		addItem((new BehaviorSwitchControl<WorldStateVelDaemon>("WorldStateVelDaemon",false))->start());
+		addItem(new BehaviorSwitchControl<ASCIIVisionBehavior>("ASCIIVisionBehavior",false));
+		addItem(new ControlBase("Debugging Tests","Stress tests"));
+		startSubMenu();
+		{
+			addItem(new BehaviorSwitchControl<MotionStressTestBehavior>("MotionStressTestBehavior",false));
+			addItem(new BehaviorSwitchControl<CrashTestBehavior>("CrashTestBehavior",false));
+			addItem(new BehaviorSwitchControl<FreezeTestBehavior>("FreezeTestBehavior",false));
+		}
+		endSubMenu();
+		addItem(new ControlBase("System Daemons","Provide some common sensor or event processing"));
+		startSubMenu();
+		{
+			addItem((new BehaviorSwitchControl<AutoGetupBehavior>("AutoGetupBehavior",false)));
+			addItem((new BehaviorSwitchControl<WorldStateVelDaemon>("WorldStateVelDaemon",false))->start());
+			addItem((new BehaviorSwitchControl<BatteryMonitorBehavior>("BatteryMonitorBehavior",false))->start());
+		}
+		endSubMenu();
 	}
 	return endSubMenu();
 }
Index: project/StartupBehavior_SetupFileAccess.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupFileAccess.cc,v
retrieving revision 1.1
retrieving revision 1.4
diff -u -d -r1.1 -r1.4
--- project/StartupBehavior_SetupFileAccess.cc	26 Jul 2003 01:48:59 -0000	1.1
+++ project/StartupBehavior_SetupFileAccess.cc	18 Oct 2004 17:01:38 -0000	1.4
@@ -2,21 +2,22 @@
 
 #include "Behaviors/Controls/ControlBase.h"
 
-#include "Behaviors/Controls/LoadPostureControl.h"
-#include "Behaviors/Controls/SavePostureControl.h"
+#include "Behaviors/Controls/PostureEditor.h"
 #include "Behaviors/Controls/RunSequenceControl.h"
 #include "Behaviors/Controls/PlaySoundControl.h"
 #include "Behaviors/Controls/DumpFileControl.h"
+#include "Behaviors/Controls/WaypointWalkControl.h"
 
 ControlBase*
 StartupBehavior::SetupFileAccess() {
 	addItem(new ControlBase("File Access","Access/load files on the memory stick"));
 	startSubMenu();
 	{ 
-		addItem(new LoadPostureControl("Load Posture",stop_id));
-		addItem(new SavePostureControl("Save Posture"));
+		addItem(new PostureEditor(stop_id));
 		addItem(new RunSequenceControl<MotionSequence::SizeXLarge>("Run Motion Sequence",stop_id));
 		addItem(new PlaySoundControl("Play Sound"));
+		addItem(new WaypointWalkControl());
+		SetupWalkEdit();
 		addItem(new DumpFileControl("Files","/ms"));
 	}
 	return endSubMenu();
Index: project/StartupBehavior_SetupModeSwitch.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc,v
retrieving revision 1.20
retrieving revision 1.33
diff -u -d -r1.20 -r1.33
--- project/StartupBehavior_SetupModeSwitch.cc	17 Mar 2004 02:06:46 -0000	1.20
+++ project/StartupBehavior_SetupModeSwitch.cc	18 Oct 2004 19:57:52 -0000	1.33
@@ -5,14 +5,21 @@
 
 #include "Behaviors/Demos/AlanBehavior.h"
 #include "Behaviors/Demos/ChaseBallBehavior.h"
-#include "Behaviors/Demos/SimpleChaseBallBehavior.h"
-#include "Behaviors/Demos/StareAtBallBehavior.h"
 #include "Behaviors/Demos/FollowHeadBehavior.h"
 #include "Behaviors/Demos/WalkToTargetMachine.h"
+#include "Behaviors/Demos/HelloWorldBehavior.h"
 #include "Behaviors/Demos/BanditMachine.h"
 #include "Behaviors/Demos/SoundTestBehavior.h"
 #include "Behaviors/Demos/ExploreMachine.h"
 #include "Behaviors/Demos/PaceTargetsMachine.h"
+#include "Behaviors/Demos/StareAtPawBehavior.h"
+#include "Behaviors/Demos/StareAtPawBehavior2.h"
+#include "Behaviors/Demos/KinematicSampleBehavior.h"
+#include "Behaviors/Demos/KinematicSampleBehavior2.h"
+#include "Behaviors/Demos/GroundPlaneBehavior.h"
+#include "Behaviors/Demos/LookForSoundBehavior.h"
+#include "Behaviors/Demos/SimpleChaseBallBehavior.h"
+#include "Behaviors/Demos/StareAtBallBehavior.h"
 
 #include "Shared/ProjectInterface.h"
 
@@ -26,17 +33,34 @@
 		BehaviorSwitchControlBase::BehaviorGroup * bg = new BehaviorSwitchControlBase::BehaviorGroup();
 
 		//put behaviors here:
+		addItem(new BehaviorSwitchControl<HelloWorldBehavior>("HelloWorldBehavior",false));
 		if(state->robotDesign&(WorldState::ERS210Mask|WorldState::ERS7Mask)) //this one only really works on the 210 or 7
 			addItem(new BehaviorSwitchControl<AlanBehavior>("AlanBehavior",bg,false));
 		addItem(new BehaviorSwitchControl<FollowHeadBehavior>("FollowHeadBehavior",bg,false));
-		addItem(new BehaviorSwitchControl<SoundTestBehavior>("SoundTestBehavior",bg,false));
+		addItem(new BehaviorSwitchControl<StareAtBallBehavior>("StareAtBallBehavior",false));
+		addItem(new BehaviorSwitchControl<SimpleChaseBallBehavior>("SimpleChaseBallBehavior",false));
 		addItem(new BehaviorSwitchControl<ChaseBallBehavior>("ChaseBallBehavior",bg,false));
-		addItem(new BehaviorSwitchControl<SimpleChaseBallBehavior>("SimpleChaseBallBehavior",bg,false));
-		addItem(new BehaviorSwitchControl<StareAtBallBehavior>("StareAtBallBehavior",bg,false));
-		addItem(new BehaviorSwitchControlBase(new WalkToTargetMachine(ProjectInterface::visPinkBallSID),bg));
-		addItem(new BehaviorSwitchControl<BanditMachine>("BanditMachine",bg,false));
-		addItem(new BehaviorSwitchControl<ExploreMachine>("ExploreMachine",bg,false));
-		addItem(new BehaviorSwitchControl<PaceTargetsMachine>("PaceTargetsMachine",bg,false));
+		addItem(new BehaviorSwitchControl<SoundTestBehavior>("SoundTestBehavior",bg,false));
+		addItem(new BehaviorSwitchControl<LookForSoundBehavior>("LookForSoundBehavior",bg,false));
+		addItem(new ControlBase("State Machine Demos","More fully developed demo applications"));
+		startSubMenu();
+		{
+			addItem(new BehaviorSwitchControlBase(new WalkToTargetMachine(ProjectInterface::visPinkBallSID),bg));
+			addItem(new BehaviorSwitchControl<BanditMachine>("BanditMachine",bg,false));
+			addItem(new BehaviorSwitchControl<ExploreMachine>("ExploreMachine",bg,false));
+			addItem(new BehaviorSwitchControl<PaceTargetsMachine>("PaceTargetsMachine",bg,false));
+		}
+		endSubMenu();
+		addItem(new ControlBase("Kinematics Demos","Showcases some of the newly developed kinematics code"));
+		startSubMenu();
+		{
+			addItem(new BehaviorSwitchControl<KinematicSampleBehavior>("KinematicSampleBehavior",bg,false));
+			addItem(new BehaviorSwitchControl<KinematicSampleBehavior2>("KinematicSampleBehavior2",bg,false));
+			addItem(new BehaviorSwitchControl<StareAtPawBehavior>("StareAtPawBehavior",bg,false));
+			addItem(new BehaviorSwitchControl<StareAtPawBehavior2>("StareAtPawBehavior2",bg,false));
+			addItem(new BehaviorSwitchControl<GroundPlaneBehavior>("GroundPlaneBehavior",bg,false));
+		}
+		endSubMenu();
 	}
 	return endSubMenu();
 }
Index: project/StartupBehavior_SetupTekkotsuMon.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupTekkotsuMon.cc,v
retrieving revision 1.12
retrieving revision 1.14
diff -u -d -r1.12 -r1.14
--- project/StartupBehavior_SetupTekkotsuMon.cc	19 Jan 2004 20:36:56 -0000	1.12
+++ project/StartupBehavior_SetupTekkotsuMon.cc	25 Aug 2004 01:09:18 -0000	1.14
@@ -18,14 +18,14 @@
 	addItem(new ControlBase("TekkotsuMon","Servers for GUIs"));
 	startSubMenu();
 	{ 
-		addItem((new BehaviorSwitchControl<RawCamBehavior>("RawCamServer",false)));
-		addItem((new BehaviorSwitchControl<SegCamBehavior>("SegCamServer",false)));
 		addItem((new BehaviorSwitchControl<HeadPointControllerBehavior>("Head Remote Control",false)));
 		addItem((new BehaviorSwitchControl<WalkControllerBehavior>("Walk Remote Control",false)));
 		addItem((new BehaviorSwitchControl<ViewWMVarsBehavior>("View WMVars",false)));
 		addItem((new BehaviorSwitchControl<WMMonitorBehavior>("Watchable Memory Monitor",false))->start());
 		addItem((new BehaviorSwitchControl<Aibo3DControllerBehavior>("Aibo 3D",false)));
 		addItem((new BehaviorSwitchControl<WorldStateSerializerBehavior>("World State Serializer",false)));
+		addItem((new BehaviorSwitchControl<RawCamBehavior>("RawCamServer",false)));
+		addItem((new BehaviorSwitchControl<SegCamBehavior>("SegCamServer",false)));
 		addItem((new BehaviorSwitchControlBase(new EStopControllerBehavior(stop_id)))->start());
 	}
 	return endSubMenu();
Index: project/StartupBehavior_SetupVision.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupVision.cc,v
retrieving revision 1.14
retrieving revision 1.16
diff -u -d -r1.14 -r1.16
--- project/StartupBehavior_SetupVision.cc	23 Feb 2004 16:17:15 -0000	1.14
+++ project/StartupBehavior_SetupVision.cc	17 Mar 2004 22:49:15 -0000	1.16
@@ -4,6 +4,7 @@
 #include "Shared/Config.h"
 
 #include "Behaviors/Controls/BehaviorSwitchControl.h"
+#include "Behaviors/Controls/NullControl.h"
 
 #include "Vision/RawCameraGenerator.h"
 #include "Vision/InterleavedYUVGenerator.h"
@@ -112,9 +113,18 @@
 			addItem(new BehaviorSwitchControlBase(defSegmentedColorGenerator));
 		addItem((new BehaviorSwitchControlBase(defRLEGenerator))->start());
 		addItem((new BehaviorSwitchControlBase(defRegionGenerator))->start());
-		addItem((new BehaviorSwitchControlBase(pball))->start());
-		addItem((new BehaviorSwitchControlBase(bball))->start());
-		addItem((new BehaviorSwitchControlBase(handball))->start());
+		if(pball)
+			addItem((new BehaviorSwitchControlBase(pball))->start());
+		else
+			addItem(new NullControl("Error: PinkBallDetectionGenerator","Color \"red\" is undefined"));
+		if(bball)
+			addItem((new BehaviorSwitchControlBase(bball))->start());
+		else
+			addItem(new NullControl("Error: BlueBallDetectionGenerator","Color \"blue\" is undefined"));
+		if(handball)
+			addItem((new BehaviorSwitchControlBase(handball))->start());
+		else
+			addItem(new NullControl("Error: HandBallDetectionGenerator","Color \"brown\" is undefined"));
 	}
 	return endSubMenu();
 }
Index: project/StartupBehavior_SetupWalkEdit.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/StartupBehavior_SetupWalkEdit.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- project/StartupBehavior_SetupWalkEdit.cc	26 Feb 2004 01:03:00 -0000	1.7
+++ project/StartupBehavior_SetupWalkEdit.cc	14 May 2004 07:18:19 -0000	1.8
@@ -10,9 +10,9 @@
  * 
  * $Author: ejt $
  * $Name:  $
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
  * $State: Exp $
- * $Date: 2004/02/26 01:03:00 $
+ * $Date: 2004/05/14 07:18:19 $
  */
 
 #include "StartupBehavior.h"
@@ -45,6 +45,8 @@
 			addItem(new ValueEditControl<double>("Hop",&walker->getWalkMC()->getWP().hop));
 			addItem(new ValueEditControl<double>("Sway",&walker->getWalkMC()->getWP().sway));
 			addItem(new ValueEditControl<long>("Period",&walker->getWalkMC()->getWP().period));
+			addItem(new ValueEditControl<long>("Use Diff Drive",&walker->getWalkMC()->getWP().useDiffDrive));
+			addItem(new ValueEditControl<float>("Sag",&walker->getWalkMC()->getWP().sag));
 		}
 		endSubMenu();
 
Index: project/ms/config/ers210.kin
===================================================================
RCS file: project/ms/config/ers210.kin
diff -N project/ms/config/ers210.kin
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/config/ers210.kin	18 Oct 2004 23:11:05 -0000	1.10
@@ -0,0 +1,1568 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+[Default]
+
+
+[LFr]
+Name:       LFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         59.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:        -59.2
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 0
+
+[LFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:         12.8
+a:         64.0
+alpha:      1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 1
+
+[LFr_LINK4]
+joint_type: 0
+theta:     -0.206996
+d:         -0.5
+a:         56.986
+alpha:      0.0
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 2
+
+[LFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 1
+
+
+[RFr]
+Name:       RFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         59.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:         59.2
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 3
+
+[RFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:        -12.8
+a:         64.0
+alpha:     -1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 4
+
+[RFr_LINK4]
+joint_type: 0
+theta:     -0.206996
+d:          0.5
+a:         56.986
+alpha:      0.0
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 5
+
+[RFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 2
+
+
+[LBk]
+Name:       LBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -59.5
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:         59.2
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 6
+
+[LBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:        -12.8
+a:         64.0
+alpha:     -1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 7
+
+[LBk_LINK4]
+joint_type: 0
+theta:     -0.350584
+d:          0.5
+a:         64.572
+alpha:      3.1415926535897932385
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 8
+
+[LBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 3
+
+
+[RBk]
+Name:       RBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -59.5
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:        -59.2
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 9
+
+[RBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:         12.8
+a:         64.0
+alpha:      1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 10
+
+[RBk_LINK4]
+joint_type: 0
+theta:     -0.350584
+d:         -0.5
+a:         64.572
+alpha:      3.1415926535897932385
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 11
+
+[RBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 4
+
+
+[Mouth]
+Name:       Mouth
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[Mouth_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         50.0
+a:         75.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Mouth_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.483530
+theta_max:  0.802851
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[Mouth_LINK3]
+joint_type: 0
+theta:      1.570796326794895
+d:         48.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.616175
+theta_max:  1.616175
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[Mouth_LINK4]
+joint_type: 0
+theta:     -1.570796326794895
+d:         19.9547
+a:         21.1774
+alpha:      1.570796326794895
+theta_min: -0.558505
+theta_max:  0.558505
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[Mouth_LINK5]
+joint_type: 0
+theta:      1.570796326794895
+d:          0.0
+a:         40.9065
+alpha:     -1.570796326794895
+theta_min: -0.872665
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 17
+
+
+[Camera]
+Name:       Camera
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[Camera_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         50.0
+a:         75.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Camera_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.483530
+theta_max:  0.802851
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[Camera_LINK3]
+joint_type: 0
+theta:      1.570796326794895
+d:         48.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.616175
+theta_max:  1.616175
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[Camera_LINK4]
+joint_type: 0
+theta:      3.1415926535897932385
+d:         66.6
+a:          0.0
+alpha:      0.0
+theta_min: -0.558505
+theta_max:  0.558505
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[Camera_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 5
+
+
+[IR]
+Name:       IR
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        6
+Motor:      0
+Stl:        0
+
+[IR_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         50.0
+a:         75.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[IR_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.483530
+theta_max:  0.802851
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[IR_LINK3]
+joint_type: 0
+theta:     -1.570796326794895
+d:         48.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.616175
+theta_max:  1.616175
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[IR_LINK4]
+joint_type: 0
+theta:     -2.02003
+d:         26.5
+a:          0.0
+alpha:     16.2027
+theta_min: -0.558505
+theta_max:  0.558505
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[IR_LINK5]
+joint_type: 0
+immobile:   1
+theta:      1.26156
+d:          0.0
+a:          0.0
+alpha:     -0.0215808
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[IR_LINK6]
+joint_type: 1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 6
+
+
+[InterestPoints]
+Length:     109
+
+[InterestPoint1]
+   name: LFr:elvtr
+  chain: LFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint2]
+   name: LFr:rotor
+  chain: LFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint3]
+   name: LFr:knee~
+  chain: LFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint4]
+   name: RFr:elvtr
+  chain: RFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint5]
+   name: RFr:rotor
+  chain: RFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint6]
+   name: RFr:knee~
+  chain: RFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint7]
+   name: LBk:elvtr
+  chain: LBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint8]
+   name: LBk:rotor
+  chain: LBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint9]
+   name: LBk:knee~
+  chain: LBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint10]
+   name: RBk:elvtr
+  chain: RBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint11]
+   name: RBk:rotor
+  chain: RBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint12]
+   name: RBk:knee~
+  chain: RBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint13]
+   name: NECK:tilt
+  chain: Camera
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint14]
+   name: NECK:pan~
+  chain: Camera
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint15]
+   name: NECK:nod~
+  chain: Camera
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint16]
+   name: MOUTH~~~~
+  chain: Mouth
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint17]
+   name: Base
+  chain: Camera
+   link: 0
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint18]
+   name: LFrPaw
+  chain: LFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint19]
+   name: RFrPaw
+  chain: RFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint20]
+   name: LBkPaw
+  chain: LBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint21]
+   name: RBkPaw
+  chain: RBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint22]
+   name: Camera
+  chain: Camera
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint23]
+   name: IR
+  chain: IR
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint24]
+   name: LowerLeftLowerLip
+  chain: Mouth
+   link: 5
+      x: 7.139
+      y: 37.069
+      z: 11.898
+[InterestPoint25]
+   name: LowerRightLowerLip
+  chain: Mouth
+   link: 5
+      x: 7.139
+      y: 37.069
+      z: -11.898
+[InterestPoint26]
+   name: UpperLeftLowerLip
+  chain: Mouth
+   link: 5
+      x: -1.827
+      y: 38.225
+      z: 11.630
+[InterestPoint27]
+   name: UpperRightLowerLip
+  chain: Mouth
+   link: 5
+      x: -1.827
+      y: 38.225
+      z: -11.630
+[InterestPoint28]
+   name: LowerLeftUpperLip
+  chain: Mouth
+   link: 4
+      x: -11.630
+      y: 19.327
+      z: 58.044
+[InterestPoint29]
+   name: LowerRightUpperLip
+  chain: Mouth
+   link: 4
+      x: 11.630
+      y: 19.327
+      z: 58.044
+[InterestPoint30]
+   name: LowerLeftSnout
+  chain: Camera
+   link: 4
+      x: -24.917
+      y: 19.968
+      z: 65.777
+[InterestPoint31]
+   name: LowerRightSnout
+  chain: Camera
+   link: 4
+      x: 24.917
+      y: 19.968
+      z: 65.777
+[InterestPoint32]
+   name: UpperLeftSnout
+  chain: Camera
+   link: 4
+      x: -20.338
+      y: -5.542
+      z: 71.216
+[InterestPoint33]
+   name: UpperRightSnout
+  chain: Camera
+   link: 4
+      x: 20.338
+      y: -5.542
+      z: 71.216
+[InterestPoint34]
+   name: LeftMicrophone
+  chain: Camera
+   link: 4
+      x: -36.515
+      y: -3.396
+      z: 21.030
+[InterestPoint35]
+   name: RightMicrophone
+  chain: Camera
+   link: 4
+      x: 36.515
+      y: -3.396
+      z: 21.030
+[InterestPoint36]
+   name: FrontHeadButton
+  chain: Camera
+   link: 4
+      x: 0
+      y: -44.415
+      z: 8.284
+[InterestPoint37]
+   name: RearHeadButton
+  chain: Camera
+   link: 4
+      x: 0
+      y: -41.221
+      z: -6.880
+[InterestPoint38]
+   name: ToeLFrPaw
+  chain: LFr
+   link: 5
+      x: 18.464
+      y: 31.529
+      z: 0
+[InterestPoint39]
+   name: ToeRFrPaw
+  chain: RFr
+   link: 5
+      x: 18.464
+      y: 31.529
+      z: 0
+[InterestPoint40]
+   name: ToeLBkPaw
+  chain: LBk
+   link: 5
+      x: -4.890
+      y: 36.210
+      z: 0
+[InterestPoint41]
+   name: ToeRBkPaw
+  chain: RBk
+   link: 5
+      x: -4.890
+      y: 36.210
+      z: 0
+[InterestPoint42]
+   name: LowerOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 45.272
+      y: 11.600
+      z: -15.843
+[InterestPoint43]
+   name: LowerInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 45.272
+      y: 11.600
+      z: -14.684
+[InterestPoint44]
+   name: LowerOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 31.457
+      y: -30.571
+      z: 15.843
+[InterestPoint45]
+   name: LowerInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 31.457
+      y: -30.571
+      z: 14.684
+[InterestPoint46]
+   name: LowerInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 45.272
+      y: 11.600
+      z: 14.684
+[InterestPoint47]
+   name: LowerOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 45.272
+      y: 11.600
+      z: 15.843
+[InterestPoint48]
+   name: LowerInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 31.457
+      y: -30.571
+      z: -14.684
+[InterestPoint49]
+   name: LowerOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 31.457
+      y: -30.571
+      z: -15.843
+[InterestPoint50]
+   name: LowerOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: -15.843
+[InterestPoint51]
+   name: LowerInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: -14.684
+[InterestPoint52]
+   name: LowerOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: 15.843
+[InterestPoint53]
+   name: LowerInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: 14.684
+[InterestPoint54]
+   name: LowerInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: 14.684
+[InterestPoint55]
+   name: LowerOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: 15.843
+[InterestPoint56]
+   name: LowerInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: -14.684
+[InterestPoint57]
+   name: LowerOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: -15.843
+[InterestPoint58]
+   name: MiddleOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: 15.843
+[InterestPoint59]
+   name: MiddleInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: 14.684
+[InterestPoint60]
+   name: MiddleInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: -14.684
+[InterestPoint61]
+   name: MiddleOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: -15.843
+[InterestPoint62]
+   name: UpperOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: -15.843
+[InterestPoint63]
+   name: UpperInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: -14.684
+[InterestPoint64]
+   name: UpperOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: .931
+      y: -25.377
+      z: 15.843
+[InterestPoint65]
+   name: UpperInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: .931
+      y: -25.377
+      z: 14.684
+[InterestPoint66]
+   name: UpperInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: 14.684
+[InterestPoint67]
+   name: UpperOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: 15.843
+[InterestPoint68]
+   name: UpperInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: .931
+      y: -25.377
+      z: -14.684
+[InterestPoint69]
+   name: UpperOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: .931
+      y: -25.377
+      z: -15.843
+[InterestPoint70]
+   name: UpperOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: -15.843
+[InterestPoint71]
+   name: UpperInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: -14.684
+[InterestPoint72]
+   name: UpperOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: 15.843
+[InterestPoint73]
+   name: UpperInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: 14.684
+[InterestPoint74]
+   name: UpperInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: 14.684
+[InterestPoint75]
+   name: UpperOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: 15.843
+[InterestPoint76]
+   name: UpperInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: -14.684
+[InterestPoint77]
+   name: UpperOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: -15.843
+[InterestPoint78]
+   name: LowerOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 42.939
+      y: 14.898
+      z: 18.749
+[InterestPoint79]
+   name: LowerInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 42.939
+      y: -14.496
+      z: -18.749
+[InterestPoint80]
+   name: LowerOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 48.284
+      y: 14.898
+      z: 17.459
+[InterestPoint81]
+   name: LowerInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 48.284
+      y: -14.496
+      z: -17.459
+[InterestPoint82]
+   name: LowerInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 42.939
+      y: -14.496
+      z: 18.749
+[InterestPoint83]
+   name: LowerOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 42.939
+      y: 14.898
+      z: -18.749
+[InterestPoint84]
+   name: LowerInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 48.284
+      y: -14.496
+      z: 17.459
+[InterestPoint85]
+   name: LowerOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 48.284
+      y: 14.898
+      z: -17.459
+[InterestPoint86]
+   name: LowerOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 48.284
+      y: 14.436
+      z: -17.459
+[InterestPoint87]
+   name: LowerInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 48.284
+      y: -14.027
+      z: 17.459
+[InterestPoint88]
+   name: LowerOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 42.939
+      y: 14.436
+      z: -18.749
+[InterestPoint89]
+   name: LowerInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 42.939
+      y: -14.027
+      z: 18.749
+[InterestPoint90]
+   name: LowerInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 48.284
+      y: -14.027
+      z: -17.459
+[InterestPoint91]
+   name: LowerOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 48.284
+      y: 14.436
+      z: 17.459
+[InterestPoint92]
+   name: LowerInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 42.939
+      y: -14.027
+      z: -18.749
+[InterestPoint93]
+   name: LowerOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 42.939
+      y: 14.436
+      z: 18.749
+[InterestPoint94]
+   name: UpperOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: 20.811
+[InterestPoint95]
+   name: UpperInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: 16.072
+      z: -20.811
+[InterestPoint96]
+   name: UpperOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: 20.811
+[InterestPoint97]
+   name: UpperInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: 16.072
+      z: -20.811
+[InterestPoint98]
+   name: UpperInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: 16.072
+      z: 20.811
+[InterestPoint99]
+   name: UpperOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: -20.811
+[InterestPoint100]
+   name: UpperInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: 16.072
+      z: 20.811
+[InterestPoint101]
+   name: UpperOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: -20.811
+[InterestPoint102]
+   name: UpperOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: -20.811
+[InterestPoint103]
+   name: UpperInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: 16.072
+      z: 20.811
+[InterestPoint104]
+   name: UpperOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: -20.811
+[InterestPoint105]
+   name: UpperInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: 16.072
+      z: 20.811
+[InterestPoint106]
+   name: UpperInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: 16.072
+      z: -20.811
+[InterestPoint107]
+   name: UpperOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: 20.811
+[InterestPoint108]
+   name: UpperInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: 16.072
+      z: -20.811
+[InterestPoint109]
+   name: UpperOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.912
+      y: -14.492
+      z: 20.811
Index: project/ms/config/ers220.kin
===================================================================
RCS file: project/ms/config/ers220.kin
diff -N project/ms/config/ers220.kin
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/config/ers220.kin	18 Oct 2004 23:11:05 -0000	1.10
@@ -0,0 +1,1416 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+[Default]
+
+
+[LFr]
+Name:       LFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         59.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:        -59.2
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 0
+
+[LFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:         12.8
+a:         64.0
+alpha:      1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 1
+
+[LFr_LINK4]
+joint_type: 0
+theta:     -0.206996
+d:         -0.5
+a:         56.986
+alpha:      0.0
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 2
+
+[LFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 1
+
+
+[RFr]
+Name:       RFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         59.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:         59.2
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 3
+
+[RFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:        -12.8
+a:         64.0
+alpha:     -1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 4
+
+[RFr_LINK4]
+joint_type: 0
+theta:     -0.206996
+d:          0.5
+a:         56.986
+alpha:      0.0
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 5
+
+[RFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 2
+
+
+[LBk]
+Name:       LBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -59.5
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:         59.2
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 6
+
+[LBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:        -12.8
+a:         64.0
+alpha:     -1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 7
+
+[LBk_LINK4]
+joint_type: 0
+theta:     -0.350584
+d:          0.5
+a:         64.572
+alpha:      3.1415926535897932385
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 8
+
+[LBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 3
+
+
+[RBk]
+Name:       RBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -59.5
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:        -59.2
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.0944
+theta_max:  2.0944
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 9
+
+[RBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:         12.8
+a:         64.0
+alpha:      1.570796326794895
+theta_min: -0.2618
+theta_max:  1.6057
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 10
+
+[RBk_LINK4]
+joint_type: 0
+theta:     -0.350584
+d:         -0.5
+a:         64.572
+alpha:      3.1415926535897932385
+theta_min: -0.5236
+theta_max:  2.6180
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 11
+
+[RBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 4
+
+
+[Camera]
+Name:       Camera
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[Camera_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         50.0
+a:         75.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Camera_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.596976
+theta_max:  0.802851
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[Camera_LINK3]
+joint_type: 0
+theta:      1.570796326794895
+d:         48.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.616175
+theta_max:  1.616175
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[Camera_LINK4]
+joint_type: 0
+theta:      3.1415926535897932385
+d:         66.6
+a:          0.0
+alpha:      0.0
+theta_min: -0.558505
+theta_max:  0.558505
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[Camera_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 5
+
+
+[IR]
+Name:       IR
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        6
+Motor:      0
+Stl:        0
+
+[IR_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         50.0
+a:         75.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[IR_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.596976
+theta_max:  0.802851
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[IR_LINK3]
+joint_type: 0
+theta:     -1.570796326794895
+d:         48.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.616175
+theta_max:  1.616175
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[IR_LINK4]
+joint_type: 0
+theta:     -2.02003
+d:         26.5
+a:          0.0
+alpha:     16.2027
+theta_min: -0.558505
+theta_max:  0.558505
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[IR_LINK5]
+joint_type: 0
+immobile:   1
+theta:      1.26156
+d:          0.0
+a:          0.0
+alpha:     -0.0215808
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[IR_LINK6]
+joint_type: 1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 6
+
+
+[InterestPoints]
+Length:     103
+
+[InterestPoint1]
+   name: LFr:elvtr
+  chain: LFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint2]
+   name: LFr:rotor
+  chain: LFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint3]
+   name: LFr:knee~
+  chain: LFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint4]
+   name: RFr:elvtr
+  chain: RFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint5]
+   name: RFr:rotor
+  chain: RFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint6]
+   name: RFr:knee~
+  chain: RFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint7]
+   name: LBk:elvtr
+  chain: LBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint8]
+   name: LBk:rotor
+  chain: LBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint9]
+   name: LBk:knee~
+  chain: LBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint10]
+   name: RBk:elvtr
+  chain: RBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint11]
+   name: RBk:rotor
+  chain: RBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint12]
+   name: RBk:knee~
+  chain: RBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint13]
+   name: NECK:tilt
+  chain: Camera
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint14]
+   name: NECK:pan~
+  chain: Camera
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint15]
+   name: NECK:nod~
+  chain: Camera
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint16]
+   name: Base
+  chain: Camera
+   link: 0
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint17]
+   name: LFrPaw
+  chain: LFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint18]
+   name: RFrPaw
+  chain: RFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint19]
+   name: LBkPaw
+  chain: LBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint20]
+   name: RBkPaw
+  chain: RBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint21]
+   name: Camera
+  chain: Camera
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint22]
+   name: IR
+  chain: IR
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint23]
+   name: LowerLeftSnout
+  chain: Camera
+   link: 4
+      x: -16.369
+      y: 14.469
+      z: 57.925
+[InterestPoint24]
+   name: LowerRightSnout
+  chain: Camera
+   link: 4
+      x: 16.369
+      y: 14.469
+      z: 57.925
+[InterestPoint25]
+   name: UpperLeftSnout
+  chain: Camera
+   link: 4
+      x: -27.545
+      y: -18.406
+      z: 57.925
+[InterestPoint26]
+   name: UpperRightSnout
+  chain: Camera
+   link: 4
+      x: 27.545
+      y: -18.406
+      z: 57.925
+[InterestPoint27]
+   name: LeftMicrophone
+  chain: Camera
+   link: 4
+      x: -42.574
+      y: -14.440
+      z: 0
+[InterestPoint28]
+   name: RightMicrophone
+  chain: Camera
+   link: 4
+      x: 42.574
+      y: -14.440
+      z: 0
+[InterestPoint29]
+   name: AntennaBase
+  chain: Camera
+   link: 4
+      x: 23.286
+      y: -36.059
+      z: -1.042
+[InterestPoint30]
+   name: AntennaTip
+  chain: Camera
+   link: 4
+      x: 23.286
+      y: -67.273
+      z: -12.955
+[InterestPoint31]
+   name: HeadLight
+  chain: Camera
+   link: 4
+      x: 0
+      y: -45.903
+      z: 37.769
+[InterestPoint32]
+   name: ToeLFrPaw
+  chain: LFr
+   link: 5
+      x: 18.464
+      y: 31.529
+      z: 0
+[InterestPoint33]
+   name: ToeRFrPaw
+  chain: RFr
+   link: 5
+      x: 18.464
+      y: 31.529
+      z: 0
+[InterestPoint34]
+   name: ToeLBkPaw
+  chain: LBk
+   link: 5
+      x: -4.890
+      y: 36.210
+      z: 0
+[InterestPoint35]
+   name: ToeRBkPaw
+  chain: RBk
+   link: 5
+      x: -4.890
+      y: 36.210
+      z: 0
+[InterestPoint36]
+   name: LowerOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 52.075
+      y: 20.986
+      z: -15.843
+[InterestPoint37]
+   name: LowerInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 52.075
+      y: 20.986
+      z: -14.684
+[InterestPoint38]
+   name: LowerOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 23.361
+      y: -30.920
+      z: 15.843
+[InterestPoint39]
+   name: LowerInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 23.361
+      y: -30.920
+      z: 14.684
+[InterestPoint40]
+   name: LowerInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 52.075
+      y: 20.986
+      z: 14.684
+[InterestPoint41]
+   name: LowerOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 52.075
+      y: 20.986
+      z: 15.843
+[InterestPoint42]
+   name: LowerInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 23.361
+      y: -30.920
+      z: -14.684
+[InterestPoint43]
+   name: LowerOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 23.361
+      y: -30.920
+      z: -15.843
+[InterestPoint44]
+   name: LowerOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: -15.843
+[InterestPoint45]
+   name: LowerInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: -14.684
+[InterestPoint46]
+   name: LowerOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: 15.843
+[InterestPoint47]
+   name: LowerInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: 14.684
+[InterestPoint48]
+   name: LowerInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: 14.684
+[InterestPoint49]
+   name: LowerOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: 45.891
+      y: -26.126
+      z: 15.843
+[InterestPoint50]
+   name: LowerInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: -14.684
+[InterestPoint51]
+   name: LowerOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 65.997
+      y: -8.442
+      z: -15.843
+[InterestPoint52]
+   name: MiddleOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: 15.843
+[InterestPoint53]
+   name: MiddleInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: 14.684
+[InterestPoint54]
+   name: MiddleInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: -14.684
+[InterestPoint55]
+   name: MiddleOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 43.912
+      y: 7.434
+      z: -15.843
+[InterestPoint56]
+   name: UpperOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: -15.843
+[InterestPoint57]
+   name: UpperInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: -14.684
+[InterestPoint58]
+   name: UpperOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 8.036
+      y: -22.656
+      z: 15.843
+[InterestPoint59]
+   name: UpperInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 8.036
+      y: -22.656
+      z: 14.684
+[InterestPoint60]
+   name: UpperInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: 14.684
+[InterestPoint61]
+   name: UpperOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 11.839
+      y: 5.510
+      z: 15.843
+[InterestPoint62]
+   name: UpperInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 8.036
+      y: -22.656
+      z: -14.684
+[InterestPoint63]
+   name: UpperOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 8.036
+      y: -22.656
+      z: -15.843
+[InterestPoint64]
+   name: UpperOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: -15.843
+[InterestPoint65]
+   name: UpperInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: -14.684
+[InterestPoint66]
+   name: UpperOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: 15.843
+[InterestPoint67]
+   name: UpperInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: 14.684
+[InterestPoint68]
+   name: UpperInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: 14.684
+[InterestPoint69]
+   name: UpperOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: -1.381
+      y: -23.945
+      z: 15.843
+[InterestPoint70]
+   name: UpperInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: -14.684
+[InterestPoint71]
+   name: UpperOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 13.646
+      y: 4.905
+      z: -15.843
+[InterestPoint72]
+   name: LowerOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 36.841
+      y: 15.300
+      z: 17.244
+[InterestPoint73]
+   name: LowerInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 36.841
+      y: -14.994
+      z: -17.244
+[InterestPoint74]
+   name: LowerOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 42.819
+      y: 15.300
+      z: 17.814
+[InterestPoint75]
+   name: LowerInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 42.819
+      y: -14.994
+      z: -17.814
+[InterestPoint76]
+   name: LowerInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 36.841
+      y: -14.994
+      z: 17.244
+[InterestPoint77]
+   name: LowerOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 36.841
+      y: 15.300
+      z: -17.244
+[InterestPoint78]
+   name: LowerInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 42.819
+      y: -14.994
+      z: 17.814
+[InterestPoint79]
+   name: LowerOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 42.819
+      y: 15.300
+      z: -17.814
+[InterestPoint80]
+   name: LowerOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 42.819
+      y: 15.925
+      z: -17.814
+[InterestPoint81]
+   name: LowerInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 42.819
+      y: -14.994
+      z: 17.814
+[InterestPoint82]
+   name: LowerOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 36.841
+      y: 15.925
+      z: -17.244
+[InterestPoint83]
+   name: LowerInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 36.841
+      y: -14.994
+      z: 17.244
+[InterestPoint84]
+   name: LowerInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 42.819
+      y: -14.994
+      z: -17.814
+[InterestPoint85]
+   name: LowerOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 42.819
+      y: 15.925
+      z: 17.814
+[InterestPoint86]
+   name: LowerInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 36.841
+      y: -14.994
+      z: -17.244
+[InterestPoint87]
+   name: LowerOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 36.841
+      y: 15.925
+      z: 17.244
+[InterestPoint88]
+   name: UpperOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: 16.736
+[InterestPoint89]
+   name: UpperInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: -16.736
+[InterestPoint90]
+   name: UpperOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: 16.736
+[InterestPoint91]
+   name: UpperInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: -16.736
+[InterestPoint92]
+   name: UpperInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: 16.736
+[InterestPoint93]
+   name: UpperOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: -16.736
+[InterestPoint94]
+   name: UpperInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: 16.736
+[InterestPoint95]
+   name: UpperOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: -16.736
+[InterestPoint96]
+   name: UpperOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: -16.736
+[InterestPoint97]
+   name: UpperInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: 16.736
+[InterestPoint98]
+   name: UpperOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: -16.736
+[InterestPoint99]
+   name: UpperInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: 16.736
+[InterestPoint100]
+   name: UpperInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: -16.736
+[InterestPoint101]
+   name: UpperOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: 16.736
+[InterestPoint102]
+   name: UpperInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 15.238
+      y: -14.994
+      z: -16.736
+[InterestPoint103]
+   name: UpperOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 15.238
+      y: 14.844
+      z: 16.736
Index: project/ms/config/ers7.kin
===================================================================
RCS file: project/ms/config/ers7.kin
diff -N project/ms/config/ers7.kin
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/config/ers7.kin	18 Oct 2004 23:11:05 -0000	1.13
@@ -0,0 +1,1879 @@
+# ----------------------------------------------------------------
+# Robot configuration File
+# ----------------------------------------------------------------
+
+[Default]
+
+
+[LFr]
+Name:       LFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         65.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:        -62.5
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.2689
+theta_max:  2.0071
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 0
+
+[LFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:          9.0
+a:         69.5
+alpha:      1.570796326794895
+theta_min: -0.1745
+theta_max:  1.5359
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 1
+
+[LFr_LINK4]
+joint_type: 0
+theta:     -0.07122
+d:         -4.7
+a:         70.1646
+alpha:      0.0
+theta_min: -0.4363
+theta_max:  2.1293
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 2
+
+[LFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 1
+
+
+[RFr]
+Name:       RFr
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RFr_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:         65.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RFr_LINK2]
+joint_type: 0
+theta:     -1.570796326794895
+d:         62.5
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.2689
+theta_max:  2.0071
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 3
+
+[RFr_LINK3]
+joint_type: 0
+theta:      0.0
+d:         -9.0
+a:         69.5
+alpha:     -1.570796326794895
+theta_min: -0.1745
+theta_max:  1.5359
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 4
+
+[RFr_LINK4]
+joint_type: 0
+theta:     -0.07122
+d:          4.7
+a:         70.1646
+alpha:      0.0
+theta_min: -0.4363
+theta_max:  2.1293
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 5
+
+[RFr_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 2
+
+
+[LBk]
+Name:       LBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[LBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -65.0
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[LBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:         62.5
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -2.2689
+theta_max:  2.0071
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 6
+
+[LBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:         -9.0
+a:         69.5
+alpha:     -1.570796326794895
+theta_min: -0.1745
+theta_max:  1.5359
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 7
+
+[LBk_LINK4]
+joint_type: 0
+theta:     -0.26686
+d:          4.7
+a:         70.1646
+alpha:      3.1415926535897932385
+theta_min: -0.4363
+theta_max:  2.1293
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 8
+
+[LBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 3
+
+
+[RBk]
+Name:       RBk
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[RBk_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:        -65.0
+alpha:     -1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[RBk_LINK2]
+joint_type: 0
+theta:      1.570796326794895
+d:        -62.5
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -2.2689
+theta_max:  2.0071
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 9
+
+[RBk_LINK3]
+joint_type: 0
+theta:      0.0
+d:          9.0
+a:         69.5
+alpha:      1.570796326794895
+theta_min: -0.1745
+theta_max:  1.5359
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 10
+
+[RBk_LINK4]
+joint_type: 0
+theta:     -0.26686
+d:         -4.7
+a:         70.1646
+alpha:      3.1415926535897932385
+theta_min: -0.4363
+theta_max:  2.1293
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 11
+
+[RBk_LINK5]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 4
+
+
+[Mouth]
+Name:       Mouth
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        5
+Motor:      0
+Stl:        0
+
+[Mouth_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         19.5
+a:         67.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Mouth_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.308996939
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[Mouth_LINK3]
+joint_type: 0
+theta:      0.0
+d:         80.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.53588974176
+theta_max:  1.53588974176
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[Mouth_LINK4]
+joint_type: 0
+theta:     -0.41241
+d:          0.0
+a:         43.6606
+alpha:      0.0
+theta_min: -0.261799387799
+theta_max:  0.785398163397
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[Mouth_LINK5]
+joint_type: 0
+theta:      0.127935
+d:          0.0
+a:         42.0076
+alpha:     -1.570796326794895
+theta_min: -0.959931088597
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 17
+
+
+[Camera]
+Name:       Camera
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        6
+Motor:      0
+Stl:        0
+
+[Camera_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         19.5
+a:         67.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Camera_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:     -1.570796326794895
+theta_min: -1.308996939
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[Camera_LINK3]
+joint_type: 0
+theta:      0.0
+d:         80.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.53588974176
+theta_max:  1.53588974176
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[Camera_LINK4]
+joint_type: 0
+theta:     -1.570796326794895
+d:          0.0
+a:         14.6
+alpha:     -1.570796326794895
+theta_min: -0.261799387799
+theta_max:  0.785398163397
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[Camera_LINK5]
+joint_type: 1
+immobile:   1
+theta:     -1.570796326794895
+d:         81.06
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[Camera_LINK6]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 5
+
+
+[NearIR]
+Name:       NearIR
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        6
+Motor:      0
+Stl:        0
+
+[NearIR_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         19.5
+a:         67.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[NearIR_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      -1.570796326794895
+theta_min: -1.308996939
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[NearIR_LINK3]
+joint_type: 0
+theta:      0.0
+d:         80.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.53588974176
+theta_max:  1.53588974176
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[NearIR_LINK4]
+joint_type: 0
+theta:      0.0249189
+d:          2.79525
+a:         76.9239
+alpha:      0.0
+theta_min: -0.261799387799
+theta_max:  0.785398163397
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[NearIR_LINK5]
+joint_type: 0
+immobile:   1
+theta:      1.50041
+d:          0.0
+a:          0.0
+alpha:      1.55997
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[NearIR_LINK6]
+joint_type: 1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 6
+
+
+[FarIR]
+Name:       FarIR
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        6
+Motor:      0
+Stl:        0
+
+[FarIR_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         19.5
+a:         67.5
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[FarIR_LINK2]
+joint_type: 0
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      -1.570796326794895
+theta_min: -1.308996939
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 12
+
+[FarIR_LINK3]
+joint_type: 0
+theta:      0.0
+d:         80.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min: -1.53588974176
+theta_max:  1.53588974176
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 13
+
+[FarIR_LINK4]
+joint_type: 0
+theta:      0.0136814
+d:         -8.04682
+a:         76.9072
+alpha:      0.0
+theta_min: -0.261799387799
+theta_max:  0.785398163397
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_output: 14
+
+[FarIR_LINK5]
+joint_type: 0
+immobile:   1
+theta:      1.52305
+d:          0.0
+a:          0.0
+alpha:      1.56055
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[FarIR_LINK6]
+joint_type: 1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 7
+
+
+[ChestIR]
+Name:       ChestIR
+DH:         1
+Fix:        0
+MinPara:    0
+dof:        3
+Motor:      0
+Stl:        0
+
+[ChestIR_LINK1]
+joint_type: 0
+immobile:   1
+theta:      0.0
+d:         -3.38397459622
+a:        109.13620668
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[ChestIR_LINK2]
+joint_type: 0
+immobile:   1
+theta:      1.0471975512
+d:          0.0
+a:          0.0
+alpha:      1.570796326794895
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+
+[ChestIR_LINK3]
+joint_type: 1
+theta:      0.0
+d:          0.0
+a:          0.0
+alpha:      0.0
+theta_min:  0.0
+theta_max:  0.0
+m:          0.0
+cx:         0.0
+cy:         0.0
+cz:         0.0
+Ixx:        0.0
+Ixy:        0.0
+Ixz:        0.0
+Iyy:        0.0
+Iyz:        0.0
+Izz:        0.0
+tekkotsu_frame: 8
+
+
+[InterestPoints]
+Length:     122
+
+[InterestPoint1]
+   name: LFr:elvtr
+  chain: LFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint2]
+   name: LFr:rotor
+  chain: LFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint3]
+   name: LFr:knee~
+  chain: LFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint4]
+   name: RFr:elvtr
+  chain: RFr
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint5]
+   name: RFr:rotor
+  chain: RFr
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint6]
+   name: RFr:knee~
+  chain: RFr
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint7]
+   name: LBk:elvtr
+  chain: LBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint8]
+   name: LBk:rotor
+  chain: LBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint9]
+   name: LBk:knee~
+  chain: LBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint10]
+   name: RBk:elvtr
+  chain: RBk
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint11]
+   name: RBk:rotor
+  chain: RBk
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint12]
+   name: RBk:knee~
+  chain: RBk
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint13]
+   name: NECK:tilt
+  chain: Camera
+   link: 2
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint14]
+   name: NECK:pan~
+  chain: Camera
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint15]
+   name: NECK:nod~
+  chain: Camera
+   link: 4
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint16]
+   name: MOUTH~~~~
+  chain: Mouth
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint17]
+   name: Base
+  chain: Camera
+   link: 0
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint18]
+   name: LFrPaw
+  chain: LFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint19]
+   name: RFrPaw
+  chain: RFr
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint20]
+   name: LBkPaw
+  chain: LBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint21]
+   name: RBkPaw
+  chain: RBk
+   link: 5
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint22]
+   name: Camera
+  chain: Camera
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint23]
+   name: NearIR
+  chain: NearIR
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint24]
+   name: FarIR
+  chain: FarIR
+   link: 6
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint25]
+   name: ChestIR
+  chain: ChestIR
+   link: 3
+      x: 0
+      y: 0
+      z: 0
+[InterestPoint26]
+   name: LowerLeftLowerLip
+  chain: Mouth
+   link: 5
+      x: 40.851
+      y: 12.275
+      z: -16.128
+[InterestPoint27]
+   name: LowerRightLowerLip
+  chain: Mouth
+   link: 5
+      x: 40.851
+      y: 12.275
+      z: 16.128
+[InterestPoint28]
+   name: UpperLeftLowerLip
+  chain: Mouth
+   link: 5
+      x: 38.378
+      y: 11.203
+      z: -11.397
+[InterestPoint29]
+   name: UpperRightLowerLip
+  chain: Mouth
+   link: 5
+      x: 38.378
+      y: 11.203
+      z: 11.397
+[InterestPoint30]
+   name: LowerLeftUpperLip
+  chain: Mouth
+   link: 4
+      x: 79.518
+      y: -22.291
+      z: -11.397
+[InterestPoint31]
+   name: LowerRightUpperLip
+  chain: Mouth
+   link: 4
+      x: 79.518
+      y: -22.291
+      z: 11.397
+[InterestPoint32]
+   name: LowerLeftSnout
+  chain: Camera
+   link: 4
+      x: 54.223
+      y: -21.146
+      z: -37.291
+[InterestPoint33]
+   name: LowerRightSnout
+  chain: Camera
+   link: 4
+      x: 54.223
+      y: -21.146
+      z: 37.291
+[InterestPoint34]
+   name: UpperLeftSnout
+  chain: Camera
+   link: 4
+      x: 54.223
+      y: 7.605
+      z: -26.284
+[InterestPoint35]
+   name: UpperRightSnout
+  chain: Camera
+   link: 4
+      x: 54.223
+      y: 7.605
+      z: 26.284
+[InterestPoint36]
+   name: LeftMicrophone
+  chain: Camera
+   link: 4
+      x: -11.156
+      y: 14.897
+      z: -46.941
+[InterestPoint37]
+   name: RightMicrophone
+  chain: Camera
+   link: 4
+      x: -11.156
+      y: 14.897
+      z: 46.941
+[InterestPoint38]
+   name: HeadButton
+  chain: Camera
+   link: 4
+      x: -7.704
+      y: 41.192
+      z: 0
+[InterestPoint39]
+   name: ToeLFrPaw
+  chain: LFr
+   link: 5
+      x: 7.180
+      y: 29.548
+      z: 0
+[InterestPoint40]
+   name: ToeRFrPaw
+  chain: RFr
+   link: 5
+      x: 7.180
+      y: 29.548
+      z: 0
+[InterestPoint41]
+   name: ToeLBkPaw
+  chain: LBk
+   link: 5
+      x: -6.414
+      y: 27.759
+      z: 0
+[InterestPoint42]
+   name: ToeRBkPaw
+  chain: RBk
+   link: 5
+      x: -6.414
+      y: 27.759
+      z: 0
+[InterestPoint43]
+   name: LowerOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 59.298
+      y: 21.239
+      z: -24.557
+[InterestPoint44]
+   name: LowerInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 59.298
+      y: 21.239
+      z: -15.158
+[InterestPoint45]
+   name: LowerOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 41.172
+      y: -33.863
+      z: 24.557
+[InterestPoint46]
+   name: LowerInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 41.172
+      y: -33.863
+      z: 15.158
+[InterestPoint47]
+   name: LowerInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 59.298
+      y: 21.239
+      z: 15.158
+[InterestPoint48]
+   name: LowerOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 59.298
+      y: 21.239
+      z: 24.557
+[InterestPoint49]
+   name: LowerInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 41.172
+      y: -33.863
+      z: -15.158
+[InterestPoint50]
+   name: LowerOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 41.172
+      y: -33.863
+      z: -24.557
+[InterestPoint51]
+   name: LowerOuterMiddleLFrShin
+  chain: LFr
+   link: 4
+      x: 63.011
+      y: -15.573
+      z: -24.557
+[InterestPoint52]
+   name: LowerInnerMiddleRFrShin
+  chain: RFr
+   link: 4
+      x: 63.011
+      y: -15.573
+      z: -15.158
+[InterestPoint53]
+   name: LowerOuterMiddleLBkShin
+  chain: LBk
+   link: 4
+      x: 75.203
+      y: -8.342
+      z: 24.557
+[InterestPoint54]
+   name: LowerInnerMiddleRBkShin
+  chain: RBk
+   link: 4
+      x: 75.203
+      y: -8.342
+      z: 15.158
+[InterestPoint55]
+   name: LowerInnerMiddleLFrShin
+  chain: LFr
+   link: 4
+      x: 63.011
+      y: -15.573
+      z: 15.158
+[InterestPoint56]
+   name: LowerOuterMiddleRFrShin
+  chain: RFr
+   link: 4
+      x: 63.011
+      y: -15.573
+      z: 24.557
+[InterestPoint57]
+   name: LowerInnerMiddleLBkShin
+  chain: LBk
+   link: 4
+      x: 75.203
+      y: -8.342
+      z: -15.158
+[InterestPoint58]
+   name: LowerOuterMiddleRBkShin
+  chain: RBk
+   link: 4
+      x: 75.203
+      y: -8.342
+      z: -24.557
+[InterestPoint59]
+   name: LowerOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: 40.581
+      y: -26.402
+      z: -24.557
+[InterestPoint60]
+   name: LowerInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: 40.581
+      y: -26.402
+      z: -15.158
+[InterestPoint61]
+   name: LowerOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 71.133
+      y: 8.187
+      z: 24.557
+[InterestPoint62]
+   name: LowerInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 71.133
+      y: 8.187
+      z: 15.158
+[InterestPoint63]
+   name: LowerInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: 40.581
+      y: -26.402
+      z: 15.158
+[InterestPoint64]
+   name: LowerOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: 40.581
+      y: -26.402
+      z: 24.557
+[InterestPoint65]
+   name: LowerInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 71.133
+      y: 8.187
+      z: -15.158
+[InterestPoint66]
+   name: LowerOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 71.133
+      y: 8.187
+      z: -24.557
+[InterestPoint67]
+   name: MiddleOuterMiddleLFrShin
+  chain: LFr
+   link: 4
+      x: 42.057
+      y: -10.714
+      z: -27.747
+[InterestPoint68]
+   name: MiddleInnerMiddleRFrShin
+  chain: RFr
+   link: 4
+      x: 42.057
+      y: -10.714
+      z: -18.353
+[InterestPoint69]
+   name: MiddleOuterMiddleLBkShin
+  chain: LBk
+   link: 4
+      x: 41.625
+      y: -11.335
+      z: 27.747
+[InterestPoint70]
+   name: MiddleInnerMiddleRBkShin
+  chain: RBk
+   link: 4
+      x: 41.625
+      y: -11.335
+      z: 18.353
+[InterestPoint71]
+   name: MiddleInnerMiddleLFrShin
+  chain: LFr
+   link: 4
+      x: 42.057
+      y: -10.714
+      z: 18.353
+[InterestPoint72]
+   name: MiddleOuterMiddleRFrShin
+  chain: RFr
+   link: 4
+      x: 42.057
+      y: -10.714
+      z: 27.747
+[InterestPoint73]
+   name: MiddleInnerMiddleLBkShin
+  chain: LBk
+   link: 4
+      x: 41.625
+      y: -11.335
+      z: -18.353
+[InterestPoint74]
+   name: MiddleOuterMiddleRBkShin
+  chain: RBk
+   link: 4
+      x: 41.625
+      y: -11.335
+      z: -27.747
+[InterestPoint75]
+   name: UpperOuterFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 29.289
+      y: 14.743
+      z: -23.426
+[InterestPoint76]
+   name: UpperInnerFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 29.289
+      y: 14.743
+      z: -14.026
+[InterestPoint77]
+   name: UpperOuterFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 2.812
+      y: -22.417
+      z: 23.426
+[InterestPoint78]
+   name: UpperInnerFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 2.812
+      y: -22.417
+      z: 14.026
+[InterestPoint79]
+   name: UpperInnerFrontLFrShin
+  chain: LFr
+   link: 4
+      x: 29.289
+      y: 14.743
+      z: 14.026
+[InterestPoint80]
+   name: UpperOuterFrontRFrShin
+  chain: RFr
+   link: 4
+      x: 29.289
+      y: 14.743
+      z: 23.426
+[InterestPoint81]
+   name: UpperInnerFrontLBkShin
+  chain: LBk
+   link: 4
+      x: 2.812
+      y: -22.417
+      z: -14.026
+[InterestPoint82]
+   name: UpperOuterFrontRBkShin
+  chain: RBk
+   link: 4
+      x: 2.812
+      y: -22.417
+      z: -23.426
+[InterestPoint83]
+   name: UpperOuterBackLFrShin
+  chain: LFr
+   link: 4
+      x: 6.397
+      y: -20.060
+      z: -23.426
+[InterestPoint84]
+   name: UpperInnerBackRFrShin
+  chain: RFr
+   link: 4
+      x: 6.397
+      y: -20.060
+      z: -14.026
+[InterestPoint85]
+   name: UpperOuterBackLBkShin
+  chain: LBk
+   link: 4
+      x: 32.869
+      y: 9.622
+      z: 23.426
+[InterestPoint86]
+   name: UpperInnerBackRBkShin
+  chain: RBk
+   link: 4
+      x: 32.869
+      y: 9.622
+      z: 14.026
+[InterestPoint87]
+   name: UpperInnerBackLFrShin
+  chain: LFr
+   link: 4
+      x: 6.397
+      y: -20.060
+      z: 14.026
+[InterestPoint88]
+   name: UpperOuterBackRFrShin
+  chain: RFr
+   link: 4
+      x: 6.397
+      y: -20.060
+      z: 23.426
+[InterestPoint89]
+   name: UpperInnerBackLBkShin
+  chain: LBk
+   link: 4
+      x: 32.869
+      y: 9.622
+      z: -14.026
+[InterestPoint90]
+   name: UpperOuterBackRBkShin
+  chain: RBk
+   link: 4
+      x: 32.869
+      y: 9.622
+      z: -23.426
+[InterestPoint91]
+   name: LowerOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: 17.189
+[InterestPoint92]
+   name: LowerInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: -17.189
+[InterestPoint93]
+   name: LowerOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: 17.189
+[InterestPoint94]
+   name: LowerInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: -17.189
+[InterestPoint95]
+   name: LowerInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: 17.189
+[InterestPoint96]
+   name: LowerOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: -17.189
+[InterestPoint97]
+   name: LowerInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: 17.189
+[InterestPoint98]
+   name: LowerOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: -17.189
+[InterestPoint99]
+   name: LowerOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: -17.189
+[InterestPoint100]
+   name: LowerInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: 17.189
+[InterestPoint101]
+   name: LowerOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: -17.189
+[InterestPoint102]
+   name: LowerInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: 17.189
+[InterestPoint103]
+   name: LowerInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: -17.189
+[InterestPoint104]
+   name: LowerOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: 17.189
+[InterestPoint105]
+   name: LowerInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 47.947
+      y: -5.043
+      z: -17.189
+[InterestPoint106]
+   name: LowerOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 47.947
+      y: 14.539
+      z: 17.189
+[InterestPoint107]
+   name: UpperOuterFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: 10.310
+      z: 17.189
+[InterestPoint108]
+   name: UpperInnerFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: -5.043
+      z: -17.189
+[InterestPoint109]
+   name: UpperOuterFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: 10.310
+      z: 17.189
+[InterestPoint110]
+   name: UpperInnerFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: -5.043
+      z: -17.189
+[InterestPoint111]
+   name: UpperInnerFrontLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: -5.043
+      z: 17.189
+[InterestPoint112]
+   name: UpperOuterFrontRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: 10.310
+      z: -17.189
+[InterestPoint113]
+   name: UpperInnerFrontLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: -5.043
+      z: 17.189
+[InterestPoint114]
+   name: UpperOuterFrontRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: 10.310
+      z: -17.189
+[InterestPoint115]
+   name: UpperOuterBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: 10.310
+      z: -17.189
+[InterestPoint116]
+   name: UpperInnerBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: -5.043
+      z: 17.189
+[InterestPoint117]
+   name: UpperOuterBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: 10.310
+      z: -17.189
+[InterestPoint118]
+   name: UpperInnerBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: -5.043
+      z: 17.189
+[InterestPoint119]
+   name: UpperInnerBackLFrThigh
+  chain: LFr
+   link: 3
+      x: 0
+      y: -5.043
+      z: -17.189
+[InterestPoint120]
+   name: UpperOuterBackRFrThigh
+  chain: RFr
+   link: 3
+      x: 0
+      y: 10.310
+      z: 17.189
+[InterestPoint121]
+   name: UpperInnerBackLBkThigh
+  chain: LBk
+   link: 3
+      x: 0
+      y: -5.043
+      z: -17.189
+[InterestPoint122]
+   name: UpperOuterBackRBkThigh
+  chain: RBk
+   link: 3
+      x: 0
+      y: 10.310
+      z: 17.189
Index: project/ms/config/tekkotsu.cfg
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/ms/config/tekkotsu.cfg,v
retrieving revision 1.39
retrieving revision 1.49
diff -u -d -r1.39 -r1.49
--- project/ms/config/tekkotsu.cfg	21 Jan 2004 07:02:44 -0000	1.39
+++ project/ms/config/tekkotsu.cfg	18 Oct 2004 21:57:13 -0000	1.49
@@ -30,15 +30,27 @@
 #     how it is being used...
 #
 ##################################################################
+####################### $Revision: 1.49 $ ########################
+################## $Date: 2004/10/18 21:57:13 $ ##################
+##################################################################
+
 
+
+##################################################################
+##################################################################
 [Wireless]
+##################################################################
+##################################################################
 # unique id for Aibo (not used by Tekkotsu, but you might want it...)
 id=1
 
 
+
+##################################################################
+##################################################################
 [Vision]
-raw_port=10011
-rle_port=10012
+##################################################################
+##################################################################
 
 # white_balance  indoor | flourescent | outdoor
 <ERS-2*>
@@ -54,14 +66,32 @@
 
 # shutter_speed  slow | mid | fast
 # slower shutter will brighten image, but increases motion blur
+<ERS-2*>
 shutter_speed=mid
+</ERS-2*>
+<ERS-7>
+shutter_speed=slow
+</ERS-7>
 
 # resolution     quarter | half | full
 # this is the resolution vision's object recognition system will run at
 resolution=full
 
+### Camera Parameters ###
 
-### Color Segmentation Threshold files: ###
+# The field of view information should be specified in degrees
+<ERS-2*>
+horizFOV=57.6
+vertFOV=47.8
+focal_length=2.18
+</ERS-2*>
+<ERS-7>
+horizFOV=56.9
+vertFOV=45.2
+focal_length=3.27
+</ERS-7>
+
+### Color Segmentation Threshold files ###
 # Threshold (.tm) files define the mapping from full color to indexed color
 # You can uncomment more than one of these - they will be loaded into
 # separate channels of the segmenter.  The only cost of loading more
@@ -94,6 +124,12 @@
 
 
 ### Image Streaming Format ###
+# These parameters control the video stream over wireless ethernet
+# transport can be either 'udp' or 'tcp'
+raw_port=10011
+raw_transport=udp
+rle_port=10012
+rle_transport=udp
 
 # rawcam_encoding   color | y_only | uv_only | u_only | v_only | y_dx_only | y_dy_only | y_dxdy_only
 rawcam_encoding=color
@@ -138,7 +174,12 @@
 rlecam_skip=1
 
 
+
+##################################################################
+##################################################################
 [Main]
+##################################################################
+##################################################################
 console_port=10001
 stderr_port=10002
 error_level=0
@@ -154,11 +195,21 @@
 use_VT100=true
 
 
+
+##################################################################
+##################################################################
 [Behaviors]
+##################################################################
+##################################################################
 # your-stuff-here?
 
 
+
+##################################################################
+##################################################################
 [Controller]
+##################################################################
+##################################################################
 gui_port=10020
 select_snd=whiip.wav
 next_snd=toc.wav
@@ -168,17 +219,65 @@
 error_snd=fart.wav
 
 
+
+##################################################################
+##################################################################
 [Motion]
+##################################################################
+##################################################################
 root=/ms/data/motion
-walk=/ms/data/motion/walk.prm
+walk=walk.prm
+<ERS-2*>
+<ERS-210>
+kinematics=/ms/config/ers210.kin
+kinematic_chains=Mouth
+</ERS-210>
+<ERS-220>
+kinematics=/ms/config/ers220.kin
+</ERS-220>
+kinematic_chains=IR
+</ERS-2*>
+<ERS-7>
+kinematics=/ms/config/ers7.kin
+kinematic_chains=Mouth
+kinematic_chains=NearIR
+kinematic_chains=FarIR
+kinematic_chains=ChestIR
+</ERS-7>
+kinematic_chains=LFr
+kinematic_chains=RFr
+kinematic_chains=LBk
+kinematic_chains=RBk
+kinematic_chains=Camera
+
 estop_on_snd=skid.wav
 estop_off_snd=yap.wav
+
+# These values are used by some behaviors to limit the
+# speed of the head to reduce wear on the joints
+# Units: radians per second
+<ERS-2*>
 max_head_tilt_speed=2.1
 max_head_pan_speed=3.0
 max_head_roll_speed=3.0
+</ERS-2*>
+<ERS-7>
+#the pan speed is revised down from Sony's maximum a bit
+max_head_tilt_speed=3.18522588
+max_head_pan_speed=5.78140315
+max_head_roll_speed=5.78140315
+</ERS-7>
+
+console_port=10003
+stderr_port=10004
 
 
+
+##################################################################
+##################################################################
 [Sound]
+##################################################################
+##################################################################
 root=/ms/data/sound
 # volume = mute | level_1 | level_2 | level_3 | <direct dB setting: 0x8000 - 0xFFFF>
 # if you directly set the decibel level, be warned sony recommends against going above 0xF600
@@ -194,8 +293,3 @@
 preload=yap.wav
 
 
-[WorldModel2]
-dm_port=10041
-hm_port=10042
-gm_port=10043
-fs_port=10044
Index: project/ms/data/motion/circles.wyp
===================================================================
RCS file: project/ms/data/motion/circles.wyp
diff -N project/ms/data/motion/circles.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/circles.wyp	30 Mar 2004 04:31:39 -0000	1.1
@@ -0,0 +1,16 @@
+#WyP
+
+#Does a one meter square pattern, turns as targets each new waypoint
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_arc EGO 0 .5 FOLLOW 0 0.1 3.1415
+add_arc EGO 0 0 FOLLOW 1.571 0.1 0
+add_arc EGO .5 0 FOLLOW 1.571 0.1 3.1415
+add_arc EGO 0 0 FOLLOW -1.571 0.1 0
+add_arc EGO 0 .25 FOLLOW 0 0.075 3.1415
+add_arc EGO 0 0 FOLLOW 1.571 0.075 0
+add_arc EGO .25 0 FOLLOW 1.571 0.075 3.1415
+add_arc EGO 0 0 FOLLOW -1.571 0.075 0
+#END
Index: project/ms/data/motion/rightkick.pos
===================================================================
RCS file: project/ms/data/motion/rightkick.pos
diff -N project/ms/data/motion/rightkick.pos
--- project/ms/data/motion/rightkick.pos	21 Sep 2003 19:44:14 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,44 +0,0 @@
-#POS
-LFr:rotor	 0.1654	 1.0000
-LFr:elvtr	 0.0228	 1.0000
-LFr:knee~	 0.4531	 1.0000
-RFr:rotor	 0.1858	 1.0000
-RFr:elvtr	-0.0349	 1.0000
-RFr:knee~	 0.9183	 1.0000
-LBk:rotor	 0.2493	 1.0000
-LBk:elvtr	 0.4389	 1.0000
-LBk:knee~	 0.8055	 1.0000
-RBk:rotor	-0.4930	 1.0000
-RBk:elvtr	 0.4275	 1.0000
-RBk:knee~	 1.1636	 1.0000
-NECK:tilt	-0.0038	 1.0000
-NECK:pan~	 0.0000	 1.0000
-NECK:roll	 0.0038	 1.0000
-TAIL:tilt	-0.0229	 1.0000
-TAIL:pan~	 0.0000	 1.0000
-MOUTH~~~~	-0.0524	 1.0000
-LED:botL~	 1.0000	 1.0000
-LED:botR~	 1.0000	 1.0000
-LED:midL~	 0.0400	 1.0000
-LED:midR~	 0.0400	 1.0000
-LED:topL~	 0.0000	 1.0000
-LED:topR~	 0.0000	 1.0000
-LED:topBr	 0.0000	 1.0000
-LED:bkL1~	 0.0000	 1.0000
-LED:bkL2~	 0.0000	 1.0000
-LED:bkL3~	 0.0000	 1.0000
-LED:bkR3~	 0.0000	 1.0000
-LED:bkR2~	 0.0000	 1.0000
-LED:bkR1~	 0.0000	 1.0000
-LED:tailL	 0.0000	 1.0000
-LED:tailC	 0.0000	 1.0000
-LED:tailR	 0.0000	 1.0000
-LED:faceB	 0.0000	 1.0000
-LED:faceA	 0.0000	 1.0000
-LED:faceC	 0.0000	 1.0000
-LED:light	 0.0000	 1.0000
-LED:tlRed	 0.0000	 1.0000
-LED:tlBlu	 0.0000	 1.0000
-EAR:left~	 1.0000	 1.0000
-EAR:right	 1.0000	 1.0000
-#END
Index: project/ms/data/motion/rkick.pos
===================================================================
RCS file: project/ms/data/motion/rkick.pos
diff -N project/ms/data/motion/rkick.pos
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/rkick.pos	8 Jul 2004 03:04:21 -0000	1.1
@@ -0,0 +1,44 @@
+#POS
+LFr:rotor	 0.1654	 1.0000
+LFr:elvtr	 0.0228	 1.0000
+LFr:knee~	 0.4531	 1.0000
+RFr:rotor	 0.1858	 1.0000
+RFr:elvtr	-0.0349	 1.0000
+RFr:knee~	 0.9183	 1.0000
+LBk:rotor	 0.2493	 1.0000
+LBk:elvtr	 0.4389	 1.0000
+LBk:knee~	 0.8055	 1.0000
+RBk:rotor	-0.4930	 1.0000
+RBk:elvtr	 0.4275	 1.0000
+RBk:knee~	 1.1636	 1.0000
+NECK:tilt	-0.0038	 1.0000
+NECK:pan~	 0.0000	 1.0000
+NECK:roll	 0.0038	 1.0000
+TAIL:tilt	-0.0229	 1.0000
+TAIL:pan~	 0.0000	 1.0000
+MOUTH~~~~	-0.0524	 1.0000
+LED:botL~	 1.0000	 1.0000
+LED:botR~	 1.0000	 1.0000
+LED:midL~	 0.0400	 1.0000
+LED:midR~	 0.0400	 1.0000
+LED:topL~	 0.0000	 1.0000
+LED:topR~	 0.0000	 1.0000
+LED:topBr	 0.0000	 1.0000
+LED:bkL1~	 0.0000	 1.0000
+LED:bkL2~	 0.0000	 1.0000
+LED:bkL3~	 0.0000	 1.0000
+LED:bkR3~	 0.0000	 1.0000
+LED:bkR2~	 0.0000	 1.0000
+LED:bkR1~	 0.0000	 1.0000
+LED:tailL	 0.0000	 1.0000
+LED:tailC	 0.0000	 1.0000
+LED:tailR	 0.0000	 1.0000
+LED:faceB	 0.0000	 1.0000
+LED:faceA	 0.0000	 1.0000
+LED:faceC	 0.0000	 1.0000
+LED:light	 0.0000	 1.0000
+LED:tlRed	 0.0000	 1.0000
+LED:tlBlu	 0.0000	 1.0000
+EAR:left~	 1.0000	 1.0000
+EAR:right	 1.0000	 1.0000
+#END
Index: project/ms/data/motion/sqbasca2.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasca2.wyp
diff -N project/ms/data/motion/sqbasca2.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasca2.wyp	30 Mar 2004 04:31:39 -0000	1.1
@@ -0,0 +1,12 @@
+#WyP
+
+#Does a one meter square pattern, turns as targets each new waypoint
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point ABS 1 0 FOLLOW 0 0.1 0
+add_point ABS 1 -1 FOLLOW 0 0.1 0
+add_point ABS 0 -1 FOLLOW 0 0.1 0
+add_point ABS 0 0 FOLLOW 0 0.1 0
+#END
Index: project/ms/data/motion/sqbasce2.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasce2.wyp
diff -N project/ms/data/motion/sqbasce2.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasce2.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,9 @@
+#WyP
+
+#Does a one meter square pattern, turns as targets each new waypoint
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point EGO 0 -1 FOLLOW 0 0.1 0
+#END
Index: project/ms/data/motion/sqbasco2.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasco2.wyp
diff -N project/ms/data/motion/sqbasco2.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasco2.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,12 @@
+#WyP
+
+#Does a one meter square pattern, turns as targets each new waypoint
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point OFF 1 0 FOLLOW 0 0.1 0
+add_point OFF 0 -1 FOLLOW 0 0.1 0
+add_point OFF -1 0 FOLLOW 0 0.1 0
+add_point OFF 0 1 FOLLOW 0 0.1 0
+#END
Index: project/ms/data/motion/sqbasica.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasica.wyp
diff -N project/ms/data/motion/sqbasica.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasica.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,16 @@
+#WyP
+
+#Does a one meter square pattern, very basic: move, stop, turn
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point ABS 1 0 FOLLOW 0 0.1 0
+add_point ABS 1 0 FOLLOW -1.571 0.1 0
+add_point ABS 1 -1 FOLLOW 0 0.1 0
+add_point ABS 1 -1 FOLLOW -1.571 0.1 0
+add_point ABS 0 -1 FOLLOW 0 0.1 0
+add_point ABS 0 -1 FOLLOW -1.571 0.1 0
+add_point ABS 0 0 FOLLOW 0 0.1 0
+add_point ABS 0 0 FOLLOW -1.571 0.1 0
+#END
Index: project/ms/data/motion/sqbasice.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasice.wyp
diff -N project/ms/data/motion/sqbasice.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasice.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,10 @@
+#WyP
+
+#Does a one meter square pattern, turns as targets each new waypoint
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point EGO 1 0 FOLLOW 0 0.1 0
+add_point EGO 0 0 FOLLOW -1.571 0.1 0
+#END
Index: project/ms/data/motion/sqbasico.wyp
===================================================================
RCS file: project/ms/data/motion/sqbasico.wyp
diff -N project/ms/data/motion/sqbasico.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqbasico.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,16 @@
+#WyP
+
+#Does a one meter square pattern, very basic: move, stop, turn
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point OFF 1 0 FOLLOW 0 0.1 0
+add_point OFF 0 0 FOLLOW -1.571 0.1 0
+add_point OFF 0 -1 FOLLOW 0 0.1 0
+add_point OFF 0 0 FOLLOW -1.571 0.1 0
+add_point OFF -1 0 FOLLOW 0 0.1 0
+add_point OFF 0 0 FOLLOW -1.571 0.1 0
+add_point OFF 0 1 FOLLOW 0 0.1 0
+add_point OFF 0 0 FOLLOW -1.571 0.1 0
+#END
Index: project/ms/data/motion/sqpush.wyp
===================================================================
RCS file: project/ms/data/motion/sqpush.wyp
diff -N project/ms/data/motion/sqpush.wyp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/ms/data/motion/sqpush.wyp	30 Mar 2004 04:31:40 -0000	1.1
@@ -0,0 +1,18 @@
+#WyP
+
+#Does a square pattern, theoretically with a ball in front of it
+#In other words, it does a little arc on each corner so the ball
+#will stay in control.
+
+#add_{point|arc} {ego|off|abs} x_val y_val {hold|follow} angle_val speed_val arc_val
+max_turn_speed 0.5
+track_path 1
+add_point EGO 0.75 0 FOLLOW 0 0.1 0
+add_point EGO 0.15 0.15 FOLLOW -1.571 0.06 -1.571
+add_point EGO 0.75 0 FOLLOW 0 0.1 0
+add_point EGO 0.15 0.15 FOLLOW -1.571 0.06 -1.571
+add_point EGO 0.75 0 FOLLOW 0 0.1 0
+add_point EGO 0.15 0.15 FOLLOW -1.571 0.06 -1.571
+add_point EGO 0.75 0 FOLLOW 0 0.1 0
+add_point EGO 0.15 0.15 FOLLOW -1.571 0.06 -1.571
+#END
Index: project/ms/open-r/mw/conf/connect.cfg
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/ms/open-r/mw/conf/connect.cfg,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- project/ms/open-r/mw/conf/connect.cfg	8 Jan 2004 22:41:57 -0000	1.6
+++ project/ms/open-r/mw/conf/connect.cfg	28 Sep 2004 23:07:08 -0000	1.7
@@ -1,6 +1,7 @@
 #System->Main
 OVirtualRobotComm.Sensor.OSensorFrameVectorData.S MainObj.SensorFrame.OSensorFrameVectorData.O
 OVirtualRobotComm.FbkImageSensor.OFbkImageVectorData.S MainObj.Image.OFbkImageVectorData.O
+OVirtualRobotAudioComm.Mic.OSoundVectorData.S MainObj.Mic.OSoundVectorData.O
 
 #Main<->Motion
 MainObj.RegisterWorldState.WorldState.S MotoObj.ReceiveWorldState.WorldState.O
Index: project/ms/open-r/mw/conf/passwd
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/project/ms/open-r/mw/conf/passwd,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- project/ms/open-r/mw/conf/passwd	28 Jul 2003 06:58:30 -0000	1.4
+++ project/ms/open-r/mw/conf/passwd	6 Jul 2004 22:46:12 -0000	1.5
@@ -1,5 +1,5 @@
-#user pass /MS/
-#guest * /MS/OPEN-R/MW/
+# FORMAT: <user> <password | *> <base_dir>
+#EXAMPLE: guest * /MS/OPEN-R/MW/
 config config /MS/CONFIG/
 data data /MS/DATA/
 ftpinst ftpinst /MS/
Index: project/templates/behavior_header.h
===================================================================
RCS file: project/templates/behavior_header.h
diff -N project/templates/behavior_header.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/templates/behavior_header.h	25 Aug 2004 01:09:24 -0000	1.1
@@ -0,0 +1,51 @@
+//-*-c++-*-
+
+// This is an empty Behavior template file.
+// Replace CLASSNAME and DESCRIPTION as appropriate, and go to town!
+
+#ifndef INCLUDED_CLASSNAME_h_
+#define INCLUDED_CLASSNAME_h_
+
+#include "Behaviors/BehaviorBase.h"
+
+//! DESCRIPTION
+class CLASSNAME : public BehaviorBase {
+public:
+	//! constructor
+	CLASSNAME() : BehaviorBase() {}
+
+	virtual void DoStart() {
+		BehaviorBase::DoStart(); // do this first
+		// <your startup code here>
+	}
+
+	virtual void DoStop() {
+		// <your shutdown code here>
+		BehaviorBase::DoStop(); // do this last
+	}
+
+	virtual void processEvent(const EventBase& e) {
+		// <your event processing code here>
+		// you can delete this function if you don't use any events...
+	}
+
+	virtual std::string getName() const { return "CLASSNAME"; }
+
+	static std::string getClassDescription() { return "DESCRIPTION"; }
+	
+protected:
+	
+};
+
+/*! @file
+ * @brief Defines CLASSNAME, which DESCRIPTION
+ * @author YOURNAMEHERE (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/25 01:09:24 $
+ */
+
+#endif
Index: project/templates/header.h
===================================================================
RCS file: project/templates/header.h
diff -N project/templates/header.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/templates/header.h	25 Aug 2004 01:09:24 -0000	1.1
@@ -0,0 +1,24 @@
+//-*-c++-*-
+#ifndef INCLUDED_CLASSNAME_h_
+#define INCLUDED_CLASSNAME_h_
+
+//! description of CLASSNAME
+class CLASSNAME {
+public:
+	
+protected:
+	
+};
+
+/*! @file
+ * @brief 
+ * @author YOURNAMEHERE (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/25 01:09:24 $
+ */
+
+#endif
Index: project/templates/implementation.cc
===================================================================
RCS file: project/templates/implementation.cc
diff -N project/templates/implementation.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ project/templates/implementation.cc	25 Aug 2004 01:09:24 -0000	1.1
@@ -0,0 +1,13 @@
+#include "CLASSNAME.h"
+
+/*! @file
+ * @brief 
+ * @author YOURNAMEHERE (Creator)
+ *
+ * $Author: ejt $
+ * $Name:  $
+ * $Revision: 1.1 $
+ * $State: Exp $
+ * $Date: 2004/08/25 01:09:24 $
+ */
+
Index: tools/Makefile
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/Makefile,v
retrieving revision 1.5
retrieving revision 1.7
diff -u -d -r1.5 -r1.7
--- tools/Makefile	24 Aug 2003 21:18:59 -0000	1.5
+++ tools/Makefile	25 Sep 2004 03:14:05 -0000	1.7
@@ -1,9 +1,9 @@
 COMPONENTS=binstrswap filtersyswarn evenmodtime mon mipaltools
-TARGETS=all clean
+TARGETS=all clean releaseCheck
 
 .PHONY: $(TARGETS)
 
-$(TARGETS):
+all clean:
 	@for dir in $(COMPONENTS); do \
 		printf "Making tool $$dir: "; \
 		(cd $$dir && $(MAKE) $@); \
@@ -11,3 +11,16 @@
 			exit 1; \
 		fi; \
 	done
+
+releaseCheck:
+	@for dir in $(dir $(shell find . -name Makefile)) ; do \
+		printf "Making tool $$dir: "; \
+		(cd $$dir && $(MAKE) clean); \
+		if [ $$? -ne 0 ] ; then \
+			exit $$?; \
+		fi; \
+		(cd $$dir && $(MAKE) all); \
+		if [ $$? -ne 0 ] ; then \
+			exit $$?; \
+		fi; \
+	done
Index: tools/buildRelease
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/buildRelease,v
retrieving revision 1.37
retrieving revision 1.48
diff -u -d -r1.37 -r1.48
--- tools/buildRelease	17 Mar 2004 04:06:58 -0000	1.37
+++ tools/buildRelease	19 Oct 2004 00:47:44 -0000	1.48
@@ -17,6 +17,8 @@
 echo New tag: ${newtag}
 echo Old tag: ${oldtag}
 
+MAKE=make;
+
 
 
 #cvs export source
@@ -82,8 +84,8 @@
 
 echo "Building patch files..."
 cd ${tmp}
-cvs rdiff -r ${oldtag} -r ${newtag} Tekkotsu > Tekkotsu_patch_$2_to_$1.diff;
-cvs rdiff -r ${oldtag} -r ${newtag} Tekkotsu/project > Tekkotsu_patch_project_$2_to_$1.diff;
+cvs rdiff -N -d -r ${oldtag} -r ${newtag} Tekkotsu > Tekkotsu_patch_$2_to_$1.diff;
+cvs rdiff -N -d -r ${oldtag} -r ${newtag} Tekkotsu/project > Tekkotsu_patch_project_$2_to_$1.diff;
 
 
 
@@ -95,14 +97,21 @@
 export TEKKOTSU_ROOT=..
 
 for x in TGT_ERS210 TGT_ERS220 TGT_ERS2xx; do
-	echo $x > ${TEKKOTSU_ROOT}/TARGET_MODEL;
+	export TEKKOTSU_TARGET_MODEL=$x;
 	printf "\n\nTesting $x build\n\n\n";
-	gmake clean;
+	${MAKE} clean;
 	if [ $? -ne 0 ] ; then
 		echo "Framework clean failed for $x"
 		exit 1;
 	fi;
-	gmake;
+	cd ${tmp}/Tekkotsu_$1/tools;
+	${MAKE} releaseCheck
+	if [ $? -ne 0 ] ; then
+		echo "Framework tools failed for $x"
+		exit 1;
+	fi;
+	cd ${tmp}/Tekkotsu_$1/project;
+	${MAKE};
 	if [ $? -ne 0 ] ; then
 		echo "Framework Build failed for $x"
 		exit 1;
@@ -113,8 +122,8 @@
 read -p "Press return when ready... (^C to stop)"
 
 mntmem $MEMSTICK_ROOT;
-rm -rf /mnt/memstick/;
-gmake update;
+rm -rf /mnt/memstick/*;
+${MAKE} update;
 if [ $? -ne 0 ] ; then
 	echo "Project build failed"
 	exit 1;
@@ -134,19 +143,27 @@
 read -p "Press return if the memstick actually works. (^C to stop)"
 
 
+
 # ERS-7 build
 cd ${tmp}/Tekkotsu_$1;
 cd project;
 
 for x in TGT_ERS7; do
-	echo $x > ${TEKKOTSU_ROOT}/TARGET_MODEL;
+	export TEKKOTSU_TARGET_MODEL=$x;
 	printf "\n\nTesting $x build\n\n\n";
-	gmake clean
+	${MAKE} clean
 	if [ $? -ne 0 ] ; then
 		echo "Framework clean failed for $x"
 		exit 1;
 	fi;
-	gmake;
+	cd ${tmp}/Tekkotsu_$1/tools;
+	${MAKE} releaseCheck
+	if [ $? -ne 0 ] ; then
+		echo "Framework tools failed for $x"
+		exit 1;
+	fi;
+	cd ${tmp}/Tekkotsu_$1/project;
+	${MAKE};
 	if [ $? -ne 0 ] ; then
 		echo "Framework Build failed for $x"
 		exit 1;
@@ -157,8 +174,8 @@
 read -p "Press return when ready... (^C to stop)"
 
 mntmem $MEMSTICK_ROOT;
-rm -rf /mnt/memstick/;
-gmake update;
+rm -rf /mnt/memstick/*;
+${MAKE} update;
 if [ $? -ne 0 ] ; then
 	echo "Project build failed"
 	exit 1;
Index: tools/crashDebug
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/crashDebug,v
retrieving revision 1.12
retrieving revision 1.17
diff -u -d -r1.12 -r1.17
--- tools/crashDebug	22 Nov 2003 20:33:02 -0000	1.12
+++ tools/crashDebug	11 Oct 2004 19:31:36 -0000	1.17
@@ -1,8 +1,10 @@
 #!/bin/bash
 
 if [ "$1" = "-h" -o "$1" = "--help" -o ! -r Makefile ] ; then
-	echo "Usage: $0 [-q] [-mipal [mi-pal_options]]";
+	echo "Usage: $0 [-q] [-f file] [-mipal [mi-pal_options]]";
 	echo "       -q     will do a quick analysis using emonLogParser (from Sony)";
+	echo "       -f     will read file as emon.log instead of looking";
+	echo "              at \$MEMSTICK_ROOT/open-r/emon.log";
 	echo "       -mipal will use the Mi-Pal tools from Griffith University";
 	echo "              mi-pal_options (if any) are passed to StackedIt";
 	echo "       If no options are given, '-q -mipal -2' is assumed.";
@@ -17,15 +19,22 @@
 	exit 2;
 fi;
 
-BUILDDIR=`grep "^BUILDDIR.*=" Makefile | cut -f 2- -d =`;
+BUILDDIR=`grep "^PROJECT_BUILDDIR.*=" Makefile | cut -f 2- -d =`;
 if [ ! "$BUILDDIR" ] ; then
-	echo "WARNING: could not find BUILDDIR specification in Makefile.";
-	echo "         Defaulting to 'build'.";
 	BUILDDIR=build;
+	echo "WARNING: could not find PROJECT_BUILDDIR specification in Makefile.";
+	echo "         Defaulting to '$BUILDDIR'.";
 fi;
+if [ ! "$TEKKOTSU_TARGET_MODEL" ] ; then
+	TEKKOTSU_TARGET_MODEL=TGT_ERS2xx;
+fi;
+BUILDDIR=`echo $BUILDDIR/PLATFORM_APERIOS_$TEKKOTSU_TARGET_MODEL`; #echo removes leading spaces
 
 if [ ! -d "$BUILDDIR" ] ; then
 	echo "ERROR: Build directory '$BUILDDIR' does not exist";
+	echo "Are you in the project directory for the code that was running";
+	echo "at the time of the crash?  You're supposed to be... otherwise";
+	echo "how am I supposed to know which project you're debugging? ;)";
 	exit 1;
 fi;
 
@@ -35,6 +44,14 @@
 	shift;
 fi;
 
+emonfile=;
+usefile=;
+if [ "$1" = "-f" ] ; then
+	usefile=true;
+	emonfile="$2";
+	shift; shift;
+fi;
+
 runmipal=;
 if [ "$1" = "-mipal" ] ; then
 	runmipal=true;
@@ -74,12 +91,16 @@
 	ln -sf mmcombo.nosnap.elf MainObj.nosnap.elf;
 	ln -sf mmcombo.nosnap.elf MotoObj.nosnap.elf;
 	ln -sf sndplay.nosnap.elf SoundPlay.nosnap.elf;
-	EMON=open-r/emon.log;
+	if [ -z "$emonfile" ] ; then
+		emonfile=${MEMSTICK_ROOT}/open-r/emon.log;
+	fi;
 else
 	ln -sf MMCOMBO.nosnap.elf MainObj.nosnap.elf;
 	ln -sf MMCOMBO.nosnap.elf MotoObj.nosnap.elf;
 	ln -sf SNDPLAY.nosnap.elf SoundPlay.nosnap.elf;
-	EMON=OPEN-R/EMON.LOG;
+	if [ -z "$emonfile" ] ; then
+		emonfile=${MEMSTICK_ROOT}/OPEN-R/EMON.LOG;
+	fi;
 fi;
 
 # remove any previous disassembly files
@@ -87,48 +108,52 @@
 # just so the elp.pl doesn't complain about not finding any previous
 touch aiboDis0.ass;
 
-${TEKKOTSU_ROOT}/tools/mntmem;
-if [ $? -ne 0 ] ; then
-
-	echo "ERROR: Memory stick not mounted.";
-	exit 1;
+if [ -z "$usefile" ] ; then
+	${TEKKOTSU_ROOT}/tools/mntmem;
+	if [ $? -ne 0 ] ; then
+		echo "ERROR: Memory stick not mounted.";
+		exit 1;
+	fi;
+fi;
 
-else
+if [ "$runquick" ] ; then
+	grep "exception code:" ${emonfile}
+	${TEKKOTSU_ROOT}/tools/emonLogParser ${emonfile} > quick-out.txt;
+	file=`sed -n '/object:/s/object:	*//p' quick-out.txt`;
+	${TEKKOTSU_ROOT}/tools/emonLogParser ${emonfile} ${file}.nosnap.elf;
+fi;
 
+if [ "$runmipal" ] ; then
 	if [ "$runquick" ] ; then
-		grep "exception code:" ${MEMSTICK_ROOT}/${EMON}
-		${TEKKOTSU_ROOT}/tools/emonLogParser ${MEMSTICK_ROOT}/${EMON} > quick-out.txt;
-		file=`sed -n '/object:/s/object:	*//p' quick-out.txt`;
-		${TEKKOTSU_ROOT}/tools/emonLogParser ${MEMSTICK_ROOT}/${EMON} ${file}.nosnap.elf;
+		echo "";
 	fi;
-
-	if [ "$runmipal" ] ; then
-		if [ "$runquick" ] ; then
-			echo "";
-		fi;
-		printf "Using StackedIt options: $options\n";
-		printf "Generating disassembly...";
-		${TEKKOTSU_ROOT}/tools/mipaltools/elp.pl -e ${MEMSTICK_ROOT}/${EMON} > elp-out.txt;
-		echo "done.";
-		
-		LINES=`cat elp-out.txt | wc -l`
-		
-		echo "*** Using elp.pl by Stuart Seymon (v2.0, 5/9/2003) ***"
-		echo "***  Mi-Pal,  Griffith University, Australia  ***"
-		echo " see ${TEKKOTSU_ROOT}/tools/mipaltools/ for more info"
-		head -`expr $LINES - 7` elp-out.txt;
-		
-		EPC=`grep "^EPC:" elp-out.txt | cut -f 2 -d x`;
-		RT=`grep "^linkTimeAddr:" elp-out.txt | cut -f 2 -d x`;
-		
-		echo
-		echo "*** Using StackedIt by Joel Fenwick (v2.0, 1/9/2003) ***"
-		echo "***   Mi-Pal,  Griffith University, Australia    ***"
-		echo " see ${TEKKOTSU_ROOT}/tools/mipaltools/ for more info"
-		${TEKKOTSU_ROOT}/tools/mipaltools/StackedIt $options $EPC $RT aiboDis1.ass ${MEMSTICK_ROOT}/${EMON};
-		
+	printf "Using StackedIt options: $options\n";
+	printf "Generating disassembly (this can take a *long* time)...";
+	${TEKKOTSU_ROOT}/tools/mipaltools/elp.pl -e ${emonfile} > elp-out.txt;
+	echo "done.";
+	
+	LINES=`cat elp-out.txt | wc -l`
+	
+	echo "*** Using elp.pl by Stuart Seymon (v2.0, 5/9/2003) ***"
+	echo "***  Mi-Pal,  Griffith University, Australia  ***"
+	echo " see ${TEKKOTSU_ROOT}/tools/mipaltools/ for more info"
+	if [ $LINES -lt 7 ] ; then
+		cat elp-out.txt
+		exit 1;
+	fi;
+	head -`expr $LINES - 7` elp-out.txt;
+	
+	EPC=`grep "^EPC:" elp-out.txt | cut -f 2 -d x`;
+	RT=`grep "^linkTimeAddr:" elp-out.txt | cut -f 2 -d x`;
+	
+	echo
+	echo "*** Using StackedIt by Joel Fenwick (v2.0, 1/9/2003) ***"
+	echo "***   Mi-Pal,  Griffith University, Australia    ***"
+	echo " see ${TEKKOTSU_ROOT}/tools/mipaltools/ for more info"
+	${TEKKOTSU_ROOT}/tools/mipaltools/StackedIt $options $EPC $RT aiboDis1.ass ${emonfile};
+	
+	if [ "$usefile" ] ; then
 		${TEKKOTSU_ROOT}/tools/umntmem;
 	fi;
-
 fi;
 
Index: tools/ftpinstall
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/ftpinstall,v
retrieving revision 1.2
retrieving revision 1.6
diff -u -d -r1.2 -r1.6
--- tools/ftpinstall	19 Feb 2004 23:07:51 -0000	1.2
+++ tools/ftpinstall	14 Jul 2004 01:19:40 -0000	1.6
@@ -12,15 +12,16 @@
 
 #----- set default options -----
 $message        = "\n ftpinstall - install MS tree using TinyFTP\n\n"
-                ."  usage:\n       mstreeput [options] addr dir\n"
-                ."  options:\n"
-                ."      -u    : username\n"
-                ."      -p    : password\n"
-                ."      -h    : help\n"
-                ."\n";
+	."  usage:\n       ftpinstall [options] addr dir\n"
+	."  options:\n"
+	."      -u    : username\n"
+	."      -p    : password\n"
+	."      -a    : use active mode (defaults to 'passive' mode)\n"
+	."      -h    : help\n"
+	."\n";
 
 use Getopt::Std;
-getopts('u:p:hH');
+getopts('u:p:hHz');
 die $message if ($opt_h || $opt_H);
 $username = $opt_u if ($opt_u);
 $password = $opt_p if ($opt_p);
@@ -37,141 +38,196 @@
 login();
 open (ST, "> ".$ENV{"HOME"}."/.tekkotsu_ftplist");
 for ($i = 0; $i < $numoflist; $i++) {
-    if ($LIST[$i] =~ /\/$/) {
-        ftpmkdir($LIST[$i]);
-    } else {
-        print "$LIST[$i]\n";
-        listenData();
-        ftpput($LIST[$i]);
+	if ($LIST[$i] =~ /\/$/) {
+		ftpmkdir($LIST[$i]);
+	} else {
+		($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+		 $atime,$mtime,$ctime,$blksize,$blocks)
+			= stat($LIST[$i]);
 
-        ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
-         $atime,$mtime,$ctime,$blksize,$blocks)
-          = stat($LIST[$i]);
-        print ST $LIST[$i]."|$mtime\n";
-    }
+		print "$LIST[$i]";
+		if ($opt_a) {
+			listenData();
+		} else {
+			connectData();
+		}
+		ftpput($LIST[$i]);
+
+		print ST $LIST[$i]."|$mtime\n";
+	}
 }
 logout();
 close(ST);
 
 #----- sub -----
 sub makecopylist {
-    my $directory = shift(@_);
-    my $numofdir;
-    my @DIRLIST;
-    my $i;
+	my $directory = shift(@_);
+	my $numofdir;
+	my @DIRLIST;
+	my $i;
 
-    opendir(DIR, $directory);
-    while ($filename = readdir(DIR)) {
-        next if ($filename =~ /^\./);
-        next if ($filename =~ /^CVS$/);
-        $path = "$directory/$filename";
-        $LIST[$numoflist++] = $path if -f $path;
-        if (-d $path) {
-            $LIST[$numoflist++] = "$path/";
-            $DIRLIST[$numofdir++] = $path;
-        }
-    }
-    close(DIR);
+	opendir(DIR, $directory);
+	while ($filename = readdir(DIR)) {
+		next if ($filename =~ /^\./);
+		next if ($filename =~ /^CVS$/);
+		$path = "$directory/$filename";
+		$LIST[$numoflist++] = $path if -f $path;
+		if (-d $path) {
+			$LIST[$numoflist++] = "$path/";
+			$DIRLIST[$numofdir++] = $path;
+		}
+	}
+	close(DIR);
 
-    for ($i = 0; $i < $numofdir; $i++) {
-        makecopylist($DIRLIST[$i]);
-    }
+	for ($i = 0; $i < $numofdir; $i++) {
+		makecopylist($DIRLIST[$i]);
+	}
 }
 
 sub login {
-    $proto = getprotobyname('tcp');
-    $port = getservbyname('ftp', 'tcp');
-    socket(COMMAND, PF_INET, SOCK_STREAM, $proto)
-        || die "can't creat socket.\n";
+	$proto = getprotobyname('tcp');
+	$port = getservbyname('ftp', 'tcp');
+	socket(COMMAND, PF_INET, SOCK_STREAM, $proto)
+		|| die "can't creat socket.\n";
     
-    $sock_addr = pack_sockaddr_in($port, inet_aton($hostname));
-    connect(COMMAND, $sock_addr) || die "cant't connect\n";
-    select(COMMAND); $|=1; select(STDOUT);
+	$sock_addr = pack_sockaddr_in($port, inet_aton($hostname));
+	connect(COMMAND, $sock_addr) || die "cant't connect\n";
+	select(COMMAND); $|=1; select(STDOUT);
 
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
     
-    print COMMAND "USER $username\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	print COMMAND "USER $username\r\n";
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
     
-    print COMMAND "PASS $password\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	print COMMAND "PASS $password\r\n";
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
 
 sub logout {
-    print COMMAND "REBT\r\n";
-    close(COMMAND);
+	print COMMAND "REBT\r\n";
+	close(COMMAND);
+}
+
+sub setType {
+	print COMMAND "TYPE I\r\n";
+	while (<COMMAND>) {
+#		print ">$_";
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
+}
+
+sub connectData {
+	socket(IN, PF_INET, SOCK_STREAM, $proto)
+		|| die "can't connect\n";
+	print COMMAND "PASV\r\n";
+	while (<COMMAND>) {
+#		print "$_\n";
+		die $_ if (/^[^123]\d+\s/);
+		if (/^\d+\s/) {
+			s/,/./g;
+			/(\d+\.\d+\.\d+\.\d+)\.(\d+)\.(\d+)/;
+			$pasvhost="$1";
+			$pasvport=$2*256+$3;
+#			print "Passive on $pasvhost:$pasvport\n";
+			$pasv_sock_addr = pack_sockaddr_in($pasvport, inet_aton($pasvhost));
+			last;
+		}
+	}
 }
 
 sub listenData {
-    for ($data_port = 5000; $data_port < 65536; $data_port++) {
-        socket(DATA, PF_INET, SOCK_STREAM, $proto)
-            || die "cant't connect\n";
+	for ($data_port = 5000; $data_port < 65536; $data_port++) {
+		socket(DATA, PF_INET, SOCK_STREAM, $proto)
+			|| die "cant't connect\n";
         
-        if (bind(DATA, pack_sockaddr_in($data_port, INADDR_ANY))) {
-            last;
-        } else {
-            die "can't bind port\n" if ($data_port == 65535);
-        }
-    }
+		if (bind(DATA, pack_sockaddr_in($data_port, INADDR_ANY))) {
+			last;
+		} else {
+			die "can't bind port\n" if ($data_port == 65535);
+		}
+	}
 
-    listen(DATA, 1) || die "listen: $!";
-    $local_sock_addr = getsockname(COMMAND);
-    ($local_port, $local_addr) = unpack_sockaddr_in($local_sock_addr);
-    $local_ip = inet_ntoa($local_addr);
-    $local_ip =~ s/\./,/g;
+	listen(DATA, 1) || die "listen: $!";
+	$local_sock_addr = getsockname(COMMAND);
+	($local_port, $local_addr) = unpack_sockaddr_in($local_sock_addr);
+	$local_ip = inet_ntoa($local_addr);
+	$local_ip =~ s/\./,/g;
 
-    printf COMMAND "PORT $local_ip,%d,%d\r\n" 
-        ,$data_port/256,$data_port%256;
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	printf COMMAND "PORT $local_ip,%d,%d\r\n" 
+		,$data_port/256,$data_port%256;
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
 
 sub ftpmkdir {
-    my $direstory = shift(@_);
+	my $direstory = shift(@_);
 
-    print COMMAND "MKD $direstory\r\n";
-    while(<COMMAND>) {
-        last if (/^\d+\s/);
-    }
+	print COMMAND "MKD $direstory\r\n";
+	while (<COMMAND>) {
+		last if (/^\d+\s/);
+	}
 }
 
 sub ftpput {
-    my $filename = shift(@_);
+	my $filename = shift(@_);
 
-    print COMMAND "TYPE I\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
-    print COMMAND "STOR $filename\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
-    accept(IN, DATA);
-    open (FILE, "$filename");
-    binmode(FILE);
+	setType();
+#	print "sending filename $filename\n";
+	if ($filename =~ /^.*\/\w{1,8}\.?\w{0,3}$/) {
+		print COMMAND "STOR $filename\r\n";
+	} else {
+		my $trunc = "";
+		if ($filename =~ /\./) {
+			$filename =~ /^(.*\/)(\w{1,8}).*\.(\w{0,3})[^\/]*$/;
+			$trunc = "$1$2.$3";
+		} else {
+			$filename =~ /^(.*\/)(\w{1,8})(\w{0,3})[^\/]*$/;
+			$trunc = "$1$2.$3";
+		}
+		print " truncated to $trunc\n";
+		print COMMAND "STOR $trunc\r\n";
+	}
+	if ($opt_a) {
+#		print "accepting...";
+		accept(IN, DATA);
+#		print "done\n";
+	} else {			
+#		print "connecting...";
+		connect(IN, $pasv_sock_addr) || die "cant't connect\n";
+#		print "done\n";
+	}
+	while (<COMMAND>) {
+#		print ">$_";
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
+#	print "opening file\n";
+	open (FILE, "$filename");
+	binmode(FILE);
 
-    while(read(FILE, $tmp, 1024)) {
-        print IN $tmp;
-    }
-    close(IN);
-    close(DATA);
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+#	print "sending data\n";
+	while (read(FILE, $tmp, 1024)) {
+#		print ".";
+		print IN "$tmp";
+	}
+	print "\n";
+#	print "closing up\n";
+	close(IN);
+	close(DATA);
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
-    
-    
Index: tools/ftpupdate
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/ftpupdate,v
retrieving revision 1.2
retrieving revision 1.6
diff -u -d -r1.2 -r1.6
--- tools/ftpupdate	19 Feb 2004 23:07:51 -0000	1.2
+++ tools/ftpupdate	14 Jul 2004 01:19:40 -0000	1.6
@@ -12,15 +12,16 @@
 
 #----- set default options -----
 $message        = "\n ftpupdate - install MS tree using TinyFTP\n\n"
-                ."  usage:\n       mstreeput [options] addr dir\n"
-                ."  options:\n"
-                ."      -u    : username\n"
-                ."      -p    : password\n"
-                ."      -h    : help\n"
-                ."\n";
+	."  usage:\n       ftpupdate [options] addr dir\n"
+	."  options:\n"
+	."      -u    : username\n"
+	."      -p    : password\n"
+	."      -a    : use active mode (defaults to 'passive' mode)\n"
+	."      -h    : help\n"
+	."\n";
 
 use Getopt::Std;
-getopts('u:p:hH');
+getopts('u:p:hHz');
 die $message if ($opt_h || $opt_H);
 $username = $opt_u if ($opt_u);
 $password = $opt_p if ($opt_p);
@@ -47,143 +48,199 @@
 open (ST, "> ".$ENV{"HOME"}."/.tekkotsu_ftplist");
 
 for ($i = 0; $i < $numoflist; $i++) {
-    if ($LIST[$i] =~ /\/$/) {
-        ftpmkdir($LIST[$i]);
-    } else {
-        ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
-         $atime,$mtime,$ctime,$blksize,$blocks)
-          = stat($LIST[$i]);
-        if ($mtime==$oldlist{$LIST[$i]}) {
-        } else {
-          print "$LIST[$i]\n";
-          listenData();
-          ftpput($LIST[$i]);
-        }
-        print ST $LIST[$i]."|$mtime\n";
-    }
+	if ($LIST[$i] =~ /\/$/) {
+		ftpmkdir($LIST[$i]);
+	} else {
+		($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+		 $atime,$mtime,$ctime,$blksize,$blocks)
+			= stat($LIST[$i]);
+
+		if ($mtime==$oldlist{$LIST[$i]}) {
+		} else {
+			print "$LIST[$i]";
+			if ($opt_a) {
+				listenData();
+			} else {
+				connectData();
+			}
+			ftpput($LIST[$i]);
+		}
+
+		print ST $LIST[$i]."|$mtime\n";
+	}
 }
 logout();
 close(ST);
 
 #----- sub -----
 sub makecopylist {
-    my $directory = shift(@_);
-    my $numofdir;
-    my @DIRLIST;
-    my $i;
+	my $directory = shift(@_);
+	my $numofdir;
+	my @DIRLIST;
+	my $i;
 
-    opendir(DIR, $directory);
-    while ($filename = readdir(DIR)) {
-        next if ($filename =~ /^\./);
-        next if ($filename =~ /^CVS$/);
-        $path = "$directory/$filename";
-        $LIST[$numoflist++] = $path if -f $path;
-        if (-d $path) {
-            $LIST[$numoflist++] = "$path/";
-            $DIRLIST[$numofdir++] = $path;
-        }
-    }
-    close(DIR);
+	opendir(DIR, $directory);
+	while ($filename = readdir(DIR)) {
+		next if ($filename =~ /^\./);
+		next if ($filename =~ /^CVS$/);
+		$path = "$directory/$filename";
+		$LIST[$numoflist++] = $path if -f $path;
+		if (-d $path) {
+			$LIST[$numoflist++] = "$path/";
+			$DIRLIST[$numofdir++] = $path;
+		}
+	}
+	close(DIR);
 
-    for ($i = 0; $i < $numofdir; $i++) {
-        makecopylist($DIRLIST[$i]);
-    }
+	for ($i = 0; $i < $numofdir; $i++) {
+		makecopylist($DIRLIST[$i]);
+	}
 }
 
 sub login {
-    $proto = getprotobyname('tcp');
-    $port = getservbyname('ftp', 'tcp');
-    socket(COMMAND, PF_INET, SOCK_STREAM, $proto)
-        || die "can't creat socket.\n";
+	$proto = getprotobyname('tcp');
+	$port = getservbyname('ftp', 'tcp');
+	socket(COMMAND, PF_INET, SOCK_STREAM, $proto)
+		|| die "can't creat socket.\n";
     
-    $sock_addr = pack_sockaddr_in($port, inet_aton($hostname));
-    connect(COMMAND, $sock_addr) || die "cant't connect\n";
-    select(COMMAND); $|=1; select(STDOUT);
+	$sock_addr = pack_sockaddr_in($port, inet_aton($hostname));
+	connect(COMMAND, $sock_addr) || die "cant't connect\n";
+	select(COMMAND); $|=1; select(STDOUT);
 
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
     
-    print COMMAND "USER $username\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	print COMMAND "USER $username\r\n";
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
     
-    print COMMAND "PASS $password\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	print COMMAND "PASS $password\r\n";
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
 
 sub logout {
-    print COMMAND "REBT\r\n";
-    close(COMMAND);
+	print COMMAND "REBT\r\n";
+	close(COMMAND);
+}
+
+sub setType {
+	print COMMAND "TYPE I\r\n";
+	while (<COMMAND>) {
+#		print ">$_";
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
+}
+
+sub connectData {
+	socket(IN, PF_INET, SOCK_STREAM, $proto)
+		|| die "can't connect\n";
+	print COMMAND "PASV\r\n";
+	while (<COMMAND>) {
+#		print "$_\n";
+		die $_ if (/^[^123]\d+\s/);
+		if (/^\d+\s/) {
+			s/,/./g;
+			/(\d+\.\d+\.\d+\.\d+)\.(\d+)\.(\d+)/;
+			$pasvhost="$1";
+			$pasvport=$2*256+$3;
+#			print "Passive on $pasvhost:$pasvport\n";
+			$pasv_sock_addr = pack_sockaddr_in($pasvport, inet_aton($pasvhost));
+			last;
+		}
+	}
 }
 
 sub listenData {
-    for ($data_port = 5000; $data_port < 65536; $data_port++) {
-        socket(DATA, PF_INET, SOCK_STREAM, $proto)
-            || die "cant't connect\n";
+	for ($data_port = 5000; $data_port < 65536; $data_port++) {
+		socket(DATA, PF_INET, SOCK_STREAM, $proto)
+			|| die "cant't connect\n";
         
-        if (bind(DATA, pack_sockaddr_in($data_port, INADDR_ANY))) {
-            last;
-        } else {
-            die "can't bind port\n" if ($data_port == 65535);
-        }
-    }
+		if (bind(DATA, pack_sockaddr_in($data_port, INADDR_ANY))) {
+			last;
+		} else {
+			die "can't bind port\n" if ($data_port == 65535);
+		}
+	}
 
-    listen(DATA, 1) || die "listen: $!";
-    $local_sock_addr = getsockname(COMMAND);
-    ($local_port, $local_addr) = unpack_sockaddr_in($local_sock_addr);
-    $local_ip = inet_ntoa($local_addr);
-    $local_ip =~ s/\./,/g;
+	listen(DATA, 1) || die "listen: $!";
+	$local_sock_addr = getsockname(COMMAND);
+	($local_port, $local_addr) = unpack_sockaddr_in($local_sock_addr);
+	$local_ip = inet_ntoa($local_addr);
+	$local_ip =~ s/\./,/g;
 
-    printf COMMAND "PORT $local_ip,%d,%d\r\n" 
-        ,$data_port/256,$data_port%256;
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+	printf COMMAND "PORT $local_ip,%d,%d\r\n" 
+		,$data_port/256,$data_port%256;
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
 
 sub ftpmkdir {
-    my $direstory = shift(@_);
+	my $direstory = shift(@_);
 
-    print COMMAND "MKD $direstory\r\n";
-    while(<COMMAND>) {
-        last if (/^\d+\s/);
-    }
+	print COMMAND "MKD $direstory\r\n";
+	while (<COMMAND>) {
+		last if (/^\d+\s/);
+	}
 }
 
 sub ftpput {
-    my $filename = shift(@_);
+	my $filename = shift(@_);
 
-    print COMMAND "TYPE I\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
-    print COMMAND "STOR $filename\r\n";
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
-    accept(IN, DATA);
-    open (FILE, "$filename");
-    binmode(FILE);
+	setType();
+#	print "sending filename $filename\n";
+	if ($filename =~ /^.*\/\w{1,8}\.?\w{0,3}$/) {
+		print COMMAND "STOR $filename\r\n";
+	} else {
+		my $trunc = "";
+		if ($filename =~ /\./) {
+			$filename =~ /^(.*\/)(\w{1,8}).*\.(\w{0,3})[^\/]*$/;
+			$trunc = "$1$2.$3";
+		} else {
+			$filename =~ /^(.*\/)(\w{1,8})(\w{0,3})[^\/]*$/;
+			$trunc = "$1$2.$3";
+		}
+		print " truncated to $trunc\n";
+		print COMMAND "STOR $trunc\r\n";
+	}
+	if ($opt_a) {
+#		print "accepting...";
+		accept(IN, DATA);
+#		print "done\n";
+	} else {			
+#		print "connecting...";
+		connect(IN, $pasv_sock_addr) || die "cant't connect\n";
+#		print "done\n";
+	}
+	while (<COMMAND>) {
+#		print ">$_";
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
+#	print "opening file\n";
+	open (FILE, "$filename");
+	binmode(FILE);
 
-    while(read(FILE, $tmp, 1024)) {
-        print IN $tmp;
-    }
-    close(IN);
-    close(DATA);
-    while(<COMMAND>) {
-        die $_ if (/^[^123]\d+\s/);
-        last if (/^\d+\s/);
-    }
+#	print "sending data\n";
+	while (read(FILE, $tmp, 1024)) {
+#		print ".";
+		print IN "$tmp";
+	}
+	print "\n";
+#	print "closing up\n";
+	close(IN);
+	close(DATA);
+	while (<COMMAND>) {
+		die $_ if (/^[^123]\d+\s/);
+		last if (/^\d+\s/);
+	}
 }
-    
-    
Index: tools/makelowercase
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/makelowercase,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- tools/makelowercase	2 Feb 2004 22:19:22 -0000	1.3
+++ tools/makelowercase	7 May 2004 04:44:24 -0000	1.5
@@ -12,15 +12,19 @@
 	if [ -r "$x" ] ; then
 		conv="`echo $x | tr '[A-Z]' '[a-z]'`";
 		if [ "$x" != "$conv" ] ; then
-			if [ -e $conv ] ; then
+			if [ -e "$conv" -a ! "$x" -ef "$conv" ] ; then
 				echo "ERROR: $conv already exists (from $x)";
 				echo "exiting..."
 				exit 1;
 			fi;
-			mv "$x" "$conv";
+			#wish i could do this:
+			# mv "$x" "$conv";
+			#but cygwin doesn't like that...
+			mv "$x" "$x"_tmp;
+			mv "$x"_tmp "$conv";
 		fi;
 		if [ $recurse -gt 0 -a -d "$conv" ] ; then
-			$0 -r $conv/*;
+			"$0" -r "$conv"/*;
 		fi;
 	fi;
 done;
Index: tools/makeuppercase
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/makeuppercase,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- tools/makeuppercase	2 Feb 2004 22:19:22 -0000	1.3
+++ tools/makeuppercase	7 May 2004 04:44:24 -0000	1.5
@@ -12,15 +12,19 @@
 	if [ -r "$x" ] ; then
 		conv="`echo $x | tr '[a-z]' '[A-Z]'`";
 		if [ "$x" != "$conv" ] ; then
-			if [ -e $conv ] ; then
+			if [ -e "$conv" -a ! "$x" -ef "$conv" ] ; then
 				echo "ERROR: $conv already exists (from $x)";
 				echo "exiting..."
 				exit 1;
 			fi;
-			mv "$x" "$conv";
+			#wish i could do this:
+			# mv "$x" "$conv";
+			#but cygwin doesn't like that...
+			mv "$x" "$x"_tmp;
+			mv "$x"_tmp "$conv";
 		fi;
 		if [ $recurse -gt 0 -a -d "$conv" ] ; then
-			$0 -r $conv/*;
+			"$0" -r "$conv"/*;
 		fi;
 	fi;
 done;
Index: tools/filtersyswarn/filtersyswarn.cc
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/filtersyswarn/filtersyswarn.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- tools/filtersyswarn/filtersyswarn.cc	25 Sep 2003 15:32:15 -0000	1.6
+++ tools/filtersyswarn/filtersyswarn.cc	24 Jul 2004 03:12:34 -0000	1.7
@@ -18,6 +18,7 @@
 		char* OPENRSDK_ROOT=getenv("OPENRSDK_ROOT");
 		OPENR+=(OPENRSDK_ROOT!=NULL)?OPENRSDK_ROOT:"/usr/local/OPEN_R_SDK/";
 	}
+	OPENR="("+OPENR+"|Shared/newmat/)";
 	string clip="  [...]";
 	
 	regcomp(&inclbegin,"^In file included from",REG_EXTENDED|REG_NOSUB);
Index: tools/mon/ControllerGUI
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/ControllerGUI,v
retrieving revision 1.4
retrieving revision 1.6
diff -u -d -r1.4 -r1.6
--- tools/mon/ControllerGUI	16 Mar 2004 17:47:09 -0000	1.4
+++ tools/mon/ControllerGUI	1 Sep 2004 04:56:58 -0000	1.6
@@ -1,2 +1,18 @@
 #!/bin/sh
+
+cd "`dirname \"$0\"`"
+if [ ! -r org/tekkotsu/mon/ControllerGUI.java ] ; then
+	echo "Cannot access org/tekkotsu/mon/ControllerGUI.java"
+	echo "Make sure this script is located at the root of the java package tree"
+	echo "(i.e. Tekkotsu/tools/mon)"
+	exit 1;
+fi;
+
+if [ ! -r org/tekkotsu/mon/ControllerGUI.class ] ; then
+	echo "Cannot access Java executable."
+	echo "Perhaps the tools need to be compiled.  Go to the Tekkotsu/tools"
+	echo "directory and type 'make'"
+	exit 1;
+fi;
+
 java -Xmx256M org.tekkotsu.mon.ControllerGUI $*
Index: tools/mon/Makefile
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/Makefile,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- tools/mon/Makefile	2 Oct 2003 04:54:17 -0000	1.18
+++ tools/mon/Makefile	16 Sep 2004 18:45:30 -0000	1.19
@@ -1,5 +1,6 @@
+AIBO3DCACHE:=.aibo3dcache
 ifneq ($(MAKECMDGOALS),clean)
-AIBO3D:=$(shell javac org/tekkotsu/aibo3d/Java3DTest.java > /dev/null 2>&1; echo $$? )
+AIBO3D:=$(shell if [ ! -r "$(AIBO3DCACHE)" ] ; then javac org/tekkotsu/aibo3d/Java3DTest.java > /dev/null 2>&1; echo $$? > "$(AIBO3DCACHE)"; fi; cat "$(AIBO3DCACHE)" )
 endif
 
 SRCS:=$(shell find . -name "*.java")
@@ -38,6 +39,9 @@
 			echo " *************************************************************************"; \
 			echo " **     Java3D package not found.  Skipping Aibo3D...                   **"; \
 			echo " **     More information: http://java.sun.com/products/java-media/3D/   **"; \
+			echo " **     (Status cached for faster recompiles - make clean to clear)     **"; \
+		else \
+			echo " **     (Using cached Java3D status - make clean to clear cache)        **"; \
 		fi;	\
 		$(if $(shell which $(CXX)), \
 			if [ `cat tmp_buildList.txt | wc -c` -gt 400 ] ; then \
@@ -53,6 +57,6 @@
 	fi;
 
 clean:
-	rm -f tmp_buildList.txt;
+	rm -f tmp_buildList.txt "$(AIBO3DCACHE)"
 	find . -name "*.class" -exec rm \{\} \;
 	find . -name "*~" -exec rm \{\} \;
Index: tools/mon/default.col
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/default.col,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- tools/mon/default.col	10 Oct 2003 00:46:15 -0000	1.6
+++ tools/mon/default.col	16 Jul 2004 22:12:10 -0000	1.7
@@ -1,10 +1,10 @@
 0 (128 128 128) "unclassified" 8 1.00
-1 (24 43 93) "blue" 8 0.75
-2 (255 255 255) "white" 8 0.75
-3 (237 131 54) "orange" 8 0.75
-4 (43 150 180) "azure" 8 0.75
-5 (36 67 23) "green" 8 0.75
-6 (209 60 97) "red" 8 0.75
-7 (200 189 123) "yellow" 8 0.75
-8 (0 0 0) "black" 8 0.75
-9 (113 80 34) "brown" 8 0.75
+1 (43 60 77) "blue" 8 0.75
+2 (75 128 45) "green" 8 0.75
+3 (142 95 33) "orange" 8 0.75
+4 (192 126 142) "pink" 8 0.75
+5 (234 21 56) "red" 8 0.75
+6 (249 249 9) "yellow" 8 0.75
+7 (9 244 225) "cyan" 8 0.75
+8 (200 14 204) "magenta" 8 0.75
+9 (76 254 247) "lime" 8 0.75
Index: tools/mon/org/tekkotsu/mon/AgentShapeInfo.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/AgentShapeInfo.java
diff -N tools/mon/org/tekkotsu/mon/AgentShapeInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/AgentShapeInfo.java	22 Apr 2004 22:46:02 -0000	1.4
@@ -0,0 +1,38 @@
+package org.tekkotsu.mon;
+
+import java.awt.Graphics2D;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+public class AgentShapeInfo extends ShapeInfo {
+	static Icon icon = new ImageIcon("org/tekkotsu/mon/icons/agent.png");
+	float orientation; // orientation of agent
+
+	public AgentShapeInfo(int _id, int _parentId, String _name, int _color,
+			float _centroidx, float _centroidy, float _centroidz,
+			float _orientation) {
+		super(_id, _parentId, _name, _color, _centroidx,_centroidy, _centroidz);
+		orientation = _orientation;
+	}
+
+	// returns left-most coordinate of object (want some buffer)
+	public float getLeft() { return centroidx-2; }
+	// returns right-most coordinate of object
+	public float getRight() { return centroidx+2; }
+	// returns top-most coordinate of object
+	public float getTop() { return centroidy-2; }
+	// returns bottom-most coordinate of object
+	public float getBottom() { return centroidy+2; }
+
+	public String toString() {
+		return (super.toString() + "(orientation " + orientation + ")");
+	}	
+	
+	public Icon getIcon() { return icon; }
+
+	public void renderTo(Graphics2D graphics) {
+		graphics.drawOval((int)(getCentroidX()+1),
+			(int)(getCentroidY()+1), 5, 5);
+	}
+	public float getOrientation() { return orientation; }
+}
Index: tools/mon/org/tekkotsu/mon/ControllerGUI.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java,v
retrieving revision 1.13
retrieving revision 1.17
diff -u -d -r1.13 -r1.17
--- tools/mon/org/tekkotsu/mon/ControllerGUI.java	5 Feb 2004 01:52:06 -0000	1.13
+++ tools/mon/org/tekkotsu/mon/ControllerGUI.java	1 Sep 2004 22:37:11 -0000	1.17
@@ -81,7 +81,10 @@
 				pre.append(" ");
 			JLabel title=new JLabel(pre.toString()+index+". "+me.title);
 			title.setBackground(me.selected?list.getSelectionBackground():list.getBackground());
-			title.setForeground(me.selected?list.getSelectionForeground():list.getForeground());
+			if(me.title.charAt(0)=='#')
+				title.setForeground(new Color(2f/3,0f,0f));
+			else
+				title.setForeground(me.selected?list.getSelectionForeground():list.getForeground());
 			title.setEnabled(list.isEnabled());
 			title.setFont(list.getFont());
 			title.setOpaque(true);
@@ -536,28 +539,39 @@
 	}
 	
 	public static void main(String s[]) throws java.lang.InterruptedException {
-    if (s.length>1) {
-      System.out.println("usage: java ControllerGUI [host]");
-      System.exit(1);
+    if (s.length>2 || s.length>0 && (s[0].equals("-h") || s[0].equals("--help"))) {
+      System.out.println("Usage: ControllerGUI [host [port]]");
+      System.out.println("       If host is unspecified, it will check previously used addresses");
+			System.out.println("       If port is unspecified, it will default to "+ControllerListener.defPort);
+			//			System.out.println("       If port is unspecified, it will be retrieved by ftp'ing the");
+			//			System.out.println("         current config file from host, and looking up the Controller");
+			//			System.out.println("         gui_port setting. (Default is "+ControllerListener.defPort+")");
+      System.exit(2);
     }
 
-    try {
-      DogConfig dogConfig=new DogConfig (s);
-      ControllerGUI controllerGUI=new ControllerGUI(dogConfig.getIP(),
-          Integer.parseInt(dogConfig.getValue("Controller", "gui_port")));
-
-      controllerGUI.addWindowListener(new WindowAdapter() {
-          public void windowClosing(WindowEvent e) { System.exit(0);} });
-			try{
-				DogConfigFTP dog_ftp=new DogConfigFTP(dogConfig.getIP(), 21, "config", "config");
-				String col=dogConfig.getValue("Vision","colors");
-				col=col.substring(col.lastIndexOf('/')+1);
-				PrintWriter out=new PrintWriter(new FileWriter("default.col"));
-				String tmp=dog_ftp.getFile(col);
-				out.print(tmp);
-				out.close();
-			} catch(Exception ex) { ex.printStackTrace(); }
-    } catch (IllegalArgumentException ex) {System.exit(0);}
+		ControllerGUI controllerGUI=null;
+		if(s.length==0) {
+			try {
+				DogConfig dogConfig=new DogConfig (s);
+				controllerGUI=new ControllerGUI(dogConfig.getIP(),Integer.parseInt(dogConfig.getValue("Controller", "gui_port")));
+			} catch (IllegalArgumentException ex) {System.exit(0);}
+		} else if(s.length>1)
+			controllerGUI=new ControllerGUI(s[0],Integer.parseInt(s[1]));
+		else
+			controllerGUI=new ControllerGUI(s[0],ControllerListener.defPort);
+		
+		controllerGUI.addWindowListener(new WindowAdapter() {
+				public void windowClosing(WindowEvent e) { System.exit(0);}
+			});
+		/*			try{
+						DogConfigFTP dog_ftp=new DogConfigFTP(dogConfig.getIP(), 21, "config", "config");
+						String col=dogConfig.getValue("Vision","colors");
+						col=col.substring(col.lastIndexOf('/')+1);
+						PrintWriter out=new PrintWriter(new FileWriter("default.col"));
+						String tmp=dog_ftp.getFile(col);
+						out.print(tmp);
+						out.close();
+						} catch(Exception ex) { ex.printStackTrace(); }*/
 	}
 
   public void keyPressed(KeyEvent e) {
Index: tools/mon/org/tekkotsu/mon/ControllerListener.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java,v
retrieving revision 1.6
retrieving revision 1.8
diff -u -d -r1.6 -r1.8
--- tools/mon/org/tekkotsu/mon/ControllerListener.java	5 Feb 2004 01:52:06 -0000	1.6
+++ tools/mon/org/tekkotsu/mon/ControllerListener.java	1 Sep 2004 22:37:11 -0000	1.8
@@ -14,7 +14,7 @@
 public class ControllerListener extends TCPListener {
 	boolean _updatedFlag=true;
 	Vector _titles;
-	Vector _menus;
+	Vector _menus=new Vector();
 	String _status=new String();
 	PrintStream _out;
 	ControllerGUI listener;
@@ -23,6 +23,7 @@
 	HashMap dynObjPorts=new HashMap();
 	InputStream sin;
 	int _connectCount=0;
+	static int defPort=10020;
 	
 	public class MenuEntry {
 		boolean hasSubmenu;
@@ -53,6 +54,8 @@
 	}
 
 	public int firstSelected() {
+		if(_menus.size()==0)
+			return -1;
 		Vector menu=(Vector)_menus.lastElement();
 		for(int i=0; i<menu.size(); i++)
 			if(((MenuEntry)menu.get(i)).selected)
Index: tools/mon/org/tekkotsu/mon/EditScriptGUI.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tools/mon/org/tekkotsu/mon/EditScriptGUI.java	4 Feb 2004 23:28:42 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/EditScriptGUI.java	1 Sep 2004 22:37:11 -0000	1.3
@@ -74,7 +74,7 @@
 				command=new JTextArea();
 				command.setLineWrap(true);
 				command.setWrapStyleWord(true); 
-				command.setColumns(30);
+				command.setColumns(35);
 				command.setRows(6);
 				{
 					JScrollPane tmp3=new JScrollPane(command);
@@ -86,6 +86,11 @@
 			{
 				Box tmp2=Box.createHorizontalBox();
 				JButton but;
+				tmp2.add(but=upBut=new JButton("Delete"));
+				but.setActionCommand("delete");
+				but.addActionListener(this);
+				tmp2.add(Box.createHorizontalStrut(strutsize));
+				tmp2.add(Box.createHorizontalGlue());
 				tmp2.add(but=upBut=new JButton("Move Up"));
 				but.setActionCommand("up");
 				but.addActionListener(this);
@@ -133,6 +138,12 @@
 			list.add(scriptIndex,list.remove(scriptIndex-1));
 		} else if(e.getActionCommand().equals("down")) {
 			list.add(scriptIndex,list.remove(scriptIndex+1));
+		} else if(e.getActionCommand().equals("delete")) {
+			int result=JOptionPane.showConfirmDialog(this,"This will delete the script.  Continue?","Warning: Really Delete?",JOptionPane.OK_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE);
+			if(result==JOptionPane.CANCEL_OPTION)
+				return;
+			list.remove(scriptIndex);
+			close();
 		} else {
 			System.out.println("EditScriptGUI: Unknown action event");
 		}
Index: tools/mon/org/tekkotsu/mon/EllipseShapeInfo.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/EllipseShapeInfo.java
diff -N tools/mon/org/tekkotsu/mon/EllipseShapeInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/EllipseShapeInfo.java	22 Apr 2004 22:46:02 -0000	1.5
@@ -0,0 +1,53 @@
+package org.tekkotsu.mon;
+
+import java.awt.Graphics2D;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+// stores info for a EllipseShape
+// note that ellipse center is same as centroid
+public class EllipseShapeInfo extends ShapeInfo {
+	static Icon icon = new ImageIcon("org/tekkotsu/mon/icons/ellipse.png");
+	float semimajor, semiminor; // length of semimajor axes
+	float orientation; // orientation of principal axis
+
+	public EllipseShapeInfo(int _id, int _parentId, String _name, int _color,
+			float _centroidx, float _centroidy, float _centroidz,
+			float _semimajor, float _semiminor,
+			float _orientation) {
+		super(_id, _parentId, _name, _color, _centroidx, _centroidy, _centroidz);
+		semimajor = _semimajor;
+		semiminor = _semiminor;
+		orientation = _orientation;
+	}
+
+	// returns left-most coordinate of object
+	public float getLeft() { return centroidx-semimajor; }
+	// returns right-most coordinate of object
+	public float getRight() { return centroidx+semimajor; }
+	// returns top-most coordinate of object
+	public float getTop() { return centroidy-semiminor; }
+	// returns bottom-most coordinate of object
+	public float getBottom() { return centroidy+semiminor; }
+
+
+	public String toString() {
+		return (super.toString() + "(semimajor " + semimajor 
+			+ ", semiminor " + semiminor 
+			+ ", orientation " + orientation + ")");
+	}
+
+	public Icon getIcon() { return icon; }
+
+	// rough rendering which doesn't take orientation into account
+	public void renderTo(Graphics2D graphics) {
+		// maybe do a hack-ish check if abs(orientation) more than pi/4?
+		graphics.drawOval((int)(getCentroidX()-semimajor+1), 
+			(int)(getCentroidY()-semiminor+1),
+			(int)(semimajor*2), (int)(semiminor*2));
+	}
+
+	public float getSemiMajor() { return semimajor; }
+	public float getSemiMinor() { return semiminor; }
+	public float getOrientation() { return orientation; }
+}
Index: tools/mon/org/tekkotsu/mon/Joints.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/Joints.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tools/mon/org/tekkotsu/mon/Joints.java	24 Feb 2004 21:13:27 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/Joints.java	16 Apr 2004 05:51:29 -0000	1.3
@@ -11,7 +11,7 @@
       //note: this is old and for the ers2xx, but, eh. doesn't hurt to leave like this
     positions=new float[18];
     duties=new float[18];
-    sensors=new float[6];
+    sensors=new float[10];
     buttons=new float[8];
   } 
 
Index: tools/mon/org/tekkotsu/mon/LineShapeInfo.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/LineShapeInfo.java
diff -N tools/mon/org/tekkotsu/mon/LineShapeInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/LineShapeInfo.java	22 Apr 2004 22:46:02 -0000	1.7
@@ -0,0 +1,65 @@
+package org.tekkotsu.mon;
+
+import java.awt.Graphics2D;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+// stores info for a LineShape
+public class LineShapeInfo extends ShapeInfo {
+	static Icon icon = new ImageIcon("org/tekkotsu/mon/icons/line.png");
+	// x/y coordinates of endpoints, with variances
+	float e1x, e1y, e1v;
+	float e2x, e2y, e2v;
+	float r, theta;
+
+	public LineShapeInfo(int _id, int _parentId, String _name, int _color,
+			float _centroidx, float _centroidy, float _centroidz,
+			float _e1x, float _e1y, float _e1v, 
+			float _e2x, float _e2y, float _e2v,
+			float _r, float _theta) {
+		
+		super(_id, _parentId, _name, _color, _centroidx, _centroidy, _centroidz);
+		e1x = _e1x;
+		e1y = _e1y;
+		e1v = _e1v;
+		e2x = _e2x;
+		e2y = _e2y;
+		e2v = _e2v;
+		r = _r;
+		theta = _theta;
+	}
+	
+	// returns left-most coordinate of object
+	public float getLeft() { return java.lang.Math.min(e1x,e2x); }
+	// returns right-most coordinate of object
+	public float getRight() { return java.lang.Math.max(e1x,e2x); }
+	// returns top-most coordinate of object
+	public float getTop() { return java.lang.Math.min(e1y,e2y); }
+	// returns bottom-most coordinate of object
+	public float getBottom() { return java.lang.Math.max(e1y,e2y); }
+
+	public String toString() {
+		return (super.toString() 
+				+ "(e1x " +e1x + ", e1y " + e1y + ", e1v " + e1v 
+				+ ", e2x " +e2x + ", e2y " + e2y + ", e2v " + e2v 
+				+ ", r " + r + ", theta " + theta + ")");
+	}
+
+	public Icon getIcon() { return icon; }
+
+	public void renderTo(Graphics2D graphics) {
+		graphics.drawLine((int)e1x,(int)e1y,(int)e2x,(int)e2y);
+		// draw circles for variance
+		graphics.drawOval((int)e1x,(int)e1y,(int)(e1v/2),(int)(e1v/2));
+		graphics.drawOval((int)e2x,(int)e2y,(int)(e2v/2),(int)(e2v/2));
+	}
+
+	public float getE1X() { return e1x; }
+	public float getE1Y() { return e1y; }
+	public float getE1V() { return e1v; }
+	public float getE2X() { return e2x; }
+	public float getE2Y() { return e2y; }
+	public float getE2V() { return e2v; }
+	public float getR() { return r; }
+	public float getTheta() { return theta; }
+}
Index: tools/mon/org/tekkotsu/mon/ShapeInfo.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/ShapeInfo.java
diff -N tools/mon/org/tekkotsu/mon/ShapeInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/ShapeInfo.java	16 Apr 2004 00:39:28 -0000	1.8
@@ -0,0 +1,35 @@
+package org.tekkotsu.mon;
+
+import java.awt.Graphics2D;
+
+// stores info for a Shape, to use as UserObject for DefaultMutableTreeNode
+public class ShapeInfo extends VisualObjectInfo {
+	float centroidx, centroidy, centroidz;
+	int color; // the color index of this object
+
+	public ShapeInfo(int _id, int _parentId, String _name, int _color,
+			float _centroidx, float _centroidy, float _centroidz) {
+		super(_id, _parentId, _name);
+		centroidx = _centroidx;
+		centroidy = _centroidy;
+		centroidz = _centroidz;
+		color = _color;
+	}
+
+	public String toString() {
+		return (super.toString() + "(color " + color + ",cx " + centroidx + ", cy " + centroidy
+			+ ", cz " + centroidz + ")");
+	}
+
+	// if no specific renderer defined, just plot a point at centroid
+	public void renderTo(Graphics2D graphics) {
+//		graphics.setColor()
+		graphics.drawOval((int)centroidx,(int)centroidy,5,5);
+	}
+
+	public float getCentroidX() { return centroidx; }
+	public float getCentroidY() { return centroidy; }
+	public float getCentroidZ() { return centroidz; }
+	public int getColor() { return color; }
+}
+
Index: tools/mon/org/tekkotsu/mon/SketchGUI.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/SketchGUI.java,v
retrieving revision 1.2
retrieving revision 1.29
diff -u -d -r1.2 -r1.29
--- tools/mon/org/tekkotsu/mon/SketchGUI.java	2 Mar 2004 14:43:21 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/SketchGUI.java	28 Sep 2004 18:56:12 -0000	1.29
@@ -8,10 +8,14 @@
 //import java.util.LinkedList;
 import java.awt.*;
 import javax.imageio.ImageIO;
+import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
 import java.awt.image.IndexColorModel;
 import java.util.Date;
 import java.util.Vector;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Comparator;
 import java.io.PrintWriter;
 import java.io.FileOutputStream;
 import java.util.prefs.Preferences;
@@ -21,21 +25,25 @@
 import java.util.StringTokenizer;
 
 public class SketchGUI extends JFrame implements ActionListener,TreeSelectionListener {
-    VisionPanel sketch;
-    JButton spawnBut;
+	boolean isCam; // true if this GUI is displaying a camera space (not world)
+
+	JFrame sketchFrame;
+    SketchPanel sketchPanel;
+//    JButton spawnBut;
     JButton refreshBut;
     JButton saveImageBut;
 	JButton refreshListBut;
     JTree sketchTree;
-	DefaultMutableTreeNode root= new DefaultMutableTreeNode("camspace");
+	DefaultMutableTreeNode root; //= new DefaultMutableTreeNode("camspace");
     JLabel status;
     float mspf=0;
     float mspfGamma=.9f;
     String state="";
     String host;
-    int port;
-    static int defSketchPort = 5873; // Default Port
-    static int defListPort = 5874; // Default Port
+    int listingPort;
+	int sketchPort;
+//    static int defListPort = 5800; // Default Port
+ //   static int defSketchPort = 5801; // Default Port
     static Preferences prefs = Preferences.userNodeForPackage(SketchGUI.class);
 	// the socket over which listings are retrieved and Sketch commands are sent
 	Socket listingSocket=null;
@@ -43,39 +51,66 @@
     BufferedReader netin = null; // network input
 
     public static void main(String args[]) {
-	if(args.length<1)
+	if(args.length<4)
 	     usage();
 
-	int port = defListPort;
-	if(args.length>1)
-	     port=Integer.parseInt(args[1]);
+    //listingPort=Integer.parseInt(args[2]);
+	int _listingPort = Integer.parseInt(args[2]);
+	int _sketchPort = Integer.parseInt(args[3]);
+ //   sketchPort=Integer.parseInt(args[3]);
 
-	SketchGUI gui = new SketchGUI(args[0],port);
+	boolean _isCam = args[1].equals("cam");
+	SketchGUI gui = new SketchGUI(args[0], _listingPort, _sketchPort, _isCam);
+//	gui.listingPort = _listingPort;
+//	gui.sketchPort = Integer.parseInt(args[3]);
 	gui.addWindowListener(new WindowAdapter() {
 		 public void windowClosing(WindowEvent e) {}});
 	gui.show();
     }
 		
     public static void usage() {
-	System.out.println("Usage: java SketchGUI host [port]");
-	System.out.println("       if port is not specified, it defaults to: [12345]"); // Default port
+	System.out.println("Usage: java org/tekkotsu/mon/SketchGUI host [cam/world] listport sketchport");
+//	System.out.println("       if port is not specified, it defaults to: [12345]"); // Default port
 	System.exit(2);
     }
 			
     public void actionPerformed(ActionEvent e) {
-	if(e.getActionCommand().compareTo("spawn")==0) {
-	    SketchGUI gui = new SketchGUI(host,port);
-	    gui.addWindowListener(new WindowAdapter() {
-		     public void windowClosing(WindowEvent e) {
-//			 System.exit(0);
-		     }});
-	    gui.show();
-	} else if(e.getActionCommand().compareTo("refresh")==0) {
-	    // Refresh the sketch tree list:
-	    
-	    // Refresh the sketch based on which are checked:
-//	    Vector sketches = new Vector();
-//	    sketch.update(sketches);
+//	if(e.getActionCommand().compareTo("spawn")==0) {
+//	    SketchGUI gui = new SketchGUI(host,port);
+//	    gui.addWindowListener(new WindowAdapter() {
+//		     public void windowClosing(WindowEvent e) {
+//		     }});
+//	    gui.show();
+	if(e.getActionCommand().compareTo("refresh")==0) {
+		// reset bounds
+		sketchPanel.leftBound = 0;
+		sketchPanel.rightBound = 176;
+		sketchPanel.topBound = 0;
+		sketchPanel.bottomBound = 144;
+/*		Enumeration nodes = root.breadthFirstEnumeration();
+		nodes.nextElement(); //skip the root
+		while (nodes.hasMoreElements()) {
+			VisualObjectInfo oinfo = (VisualObjectInfo)(((DefaultMutableTreeNode)(nodes.nextElement())).getUserObject());
+			sketchPanel.scaleToVisualObject(oinfo);
+		}*/
+
+		TreePath[] paths = sketchTree.getSelectionPaths();
+		for (int path_i = 0; path_i < paths.length; path_i++) {
+			DefaultMutableTreeNode node 
+				=(DefaultMutableTreeNode)(paths[path_i].getLastPathComponent());
+		
+			if (node == root) continue;
+			VisualObjectInfo vinfo = (VisualObjectInfo)(node.getUserObject());
+			sketchPanel.scaleToVisualObject(vinfo);
+		}
+
+		Graphics2D g = sketchPanel._image.createGraphics();
+		g.setBackground(Color.GRAY);
+		g.clearRect(0,0,176,144);
+		sketchPanel.repaint();
+		valueChanged(null); // redraw
+		sketchPanel.repaint();
+		valueChanged(null); // redraw
 	} else if(e.getActionCommand().compareTo("saveimg")==0) {
 	    File cursavepath = new File(prefs.get("cursavepath",""));
 	    JFileChooser dia=new JFileChooser(cursavepath);
@@ -96,7 +131,7 @@
 		}
 		try {
 			FileOutputStream fileout=new FileOutputStream(dia.getSelectedFile().getParent()+File.separator+base+"."+format);
-			ImageIO.write(sketch.getListener().getImage(),format,fileout);
+			ImageIO.write(sketchPanel.getListener().getImage(),format,fileout);
 		} catch(Exception ex) {}
 	    }
 	} else if(e.getActionCommand().compareTo("refreshlist")==0) {
@@ -106,11 +141,22 @@
 		root.removeAllChildren();
 		// read in new sketch listing
 		try {
+			// reset bounds
+			sketchPanel.leftBound = 0;
+			sketchPanel.rightBound = 176;
+			sketchPanel.topBound = 0;
+			sketchPanel.bottomBound = 144;
+
 			String inputLine;
 			System.out.println(inputLine = netin.readLine());
 			while((inputLine=netin.readLine()).compareTo("list end") != 0) {
-				// parse id
+				// parse type (sketch or shape)	
 				StringTokenizer st = new StringTokenizer(inputLine,": ");
+				String type = st.nextToken();
+
+				// parse id
+				inputLine = netin.readLine();
+				st = new StringTokenizer(inputLine,": ");
 				st.nextToken();
 				int id = Integer.parseInt(st.nextToken());
 				
@@ -126,33 +172,144 @@
 				st.nextToken();
 				String name = st.nextToken();
 
-
 				// create node
-				System.out.println("id:"+id+"parentId:"+parentId+"name:"+name);
-				DefaultMutableTreeNode newnode = new DefaultMutableTreeNode(new SketchInfo(id, parentId, name));
+				System.out.println(type + " id:"+id+"parentId:"+parentId+"name:"+name);
+				VisualObjectInfo oinfo;
+				if(type.equals("sketch")) {
+					oinfo = new SketchInfo(id, parentId, name);
+				} else if (type.equals("shape")) {
+					inputLine = netin.readLine();
+					st = new StringTokenizer(inputLine,": ");
+					st.nextToken();
+					int shapetype = Integer.parseInt(st.nextToken());
+					System.out.println("shapetype:" + shapetype);
+
+					// parse shape color
+					inputLine = netin.readLine();
+					st = new StringTokenizer(inputLine,": ");
+					st.nextToken();
+					int color = Integer.parseInt(st.nextToken());
+					System.out.println("color:" + color);
+
+					inputLine = netin.readLine();
+					st = new StringTokenizer(inputLine,": ");
+					st.nextToken();
+					float cx = Float.parseFloat(st.nextToken());
+					float cy = Float.parseFloat(st.nextToken());
+					float cz = Float.parseFloat(st.nextToken());
+					System.out.println("cxyz:" +cx+" "+cy+" "+cz);
+
+					if(shapetype == 1) { // lineshape
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float e1x = Float.parseFloat(st.nextToken());
+						float e1y = Float.parseFloat(st.nextToken());
+						float e1v = Float.parseFloat(st.nextToken());
+						System.out.println("e1xyv:"+e1x+" "+e1y +" "+e1v);
+
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float e2x = Float.parseFloat(st.nextToken());
+						float e2y = Float.parseFloat(st.nextToken());
+						float e2v = Float.parseFloat(st.nextToken());
+						System.out.println("e1xyv:"+e1x+" "+e1y +" "+e1v);
+
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float r = Float.parseFloat(st.nextToken());
+						System.out.println("r:"+r);
+
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float theta = Float.parseFloat(st.nextToken());
+						System.out.println("theta:"+theta);
+
+						oinfo = new LineShapeInfo(id, parentId, name, color,
+							cx,cy,cz, e1x, e1y, e1v, e2x, e2y, e2v, r, theta);
+
+					} else if(shapetype == 2) { // ellipseshape
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float semimajor = Float.parseFloat(st.nextToken());
+						float semiminor = Float.parseFloat(st.nextToken());
+						System.out.println("axes:"+semimajor+" "+semiminor);
+
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float orientation = Float.parseFloat(st.nextToken());
+						System.out.println("orientation:"+orientation);
+
+						oinfo = new EllipseShapeInfo(id,parentId,name,color,
+								cx,cy,cz, semimajor, semiminor, orientation);
+
+					} else if (shapetype == 4) { // agentshape
+						inputLine = netin.readLine();
+						st = new StringTokenizer(inputLine,": ");
+						st.nextToken();
+						float orientation = Float.parseFloat(st.nextToken());
+						System.out.println("orientation:"+orientation);
+
+						oinfo = new AgentShapeInfo(id,parentId, name, color,
+								cx,cy,cz, orientation);
+					} else {
+						System.out.println("Invalid shape!");
+						oinfo = new ShapeInfo(id, parentId, name, color,
+								cx,cy,cz);
+					}
+				} else {
+					System.out.println("Invalid type!");
+					oinfo = new VisualObjectInfo(id, parentId, name);
+				}
+	
+				if(!isCam)
+					sketchPanel.scaleToVisualObject(oinfo);
+
+				DefaultMutableTreeNode newnode = new DefaultMutableTreeNode(oinfo);
 				root.add(newnode);
 
-				// pair up nodes with parents, quite inefficiently (?)
-//				Enumeration nodes = root.preorderEnumeration();
+
+				sketchTree.updateUI();
+				
+			}
+			// pair up nodes with parents, quite inefficiently (?)
+//			Enumeration nodes = root.preorderEnumeration();
+//			while(nodes.hasMoreElements()) {
+//				SketchInfo cur = (SketchInfo)(nodes.nextElement());
 //				while(nodes.hasMoreElements()) {
-//					SketchInfo cur = (SketchInfo)(nodes.nextElement());
-//					while(nodes.hasMoreElements()) {
-//						
-//					}
+//					
 //				}
-			
-				
-				DefaultMutableTreeNode curNode = root;
-				while((curNode = curNode.getNextNode()) != null) {
-					DefaultMutableTreeNode potentialParent = root;
-					while((potentialParent = potentialParent.getNextNode()) != null) {
-						if(((SketchInfo)(curNode.getUserObject())).parentId == ((SketchInfo)(potentialParent.getUserObject())).id && !potentialParent.isNodeAncestor(curNode)) {
-							potentialParent.add(curNode);
-						}
+//			}
+			// pair children with parents
+			DefaultMutableTreeNode curNode = root;
+			while((curNode = curNode.getNextNode()) != null) {
+				DefaultMutableTreeNode potentialParent = root;
+				while((potentialParent = potentialParent.getNextNode()) != null) {
+					if(((VisualObjectInfo)(curNode.getUserObject())).parentId == ((VisualObjectInfo)(potentialParent.getUserObject())).id && !potentialParent.isNodeAncestor(curNode)) {
+						potentialParent.add(curNode);
 					}
-
 				}
+
+			}
+			sortTree(root);		
+
+			// display the first sketch
+			SketchInfo firstinfo = (SketchInfo)(((DefaultMutableTreeNode)(root.getFirstChild())).getUserObject());
+			netout.println("get "+firstinfo.getId());
+			while((inputLine=netin.readLine()).compareTo("get end") != 0) {
+				System.out.println(inputLine);
+			}	
+			netout.println("get "+firstinfo.getId()); // why a 2nd time?
+			while((inputLine=netin.readLine()).compareTo("get end") != 0) {
+				System.out.println(inputLine);
 			}
+
+
 			System.out.println(inputLine);
 			//sketchTree = new JTree(root); // is this right?
 			//JScrollPane treeView = new JScrollPane(sketchTree);
@@ -170,15 +327,23 @@
 	}
     }
 
-    public SketchGUI(String host, int port) {
+    public SketchGUI(String host, int _listingPort, int _sketchPort, 
+			boolean _isCam) {
 	super();
 	this.host = host;
-	this.port = port;
+	this.listingPort = _listingPort;
+	this.sketchPort = _sketchPort;
+	this.isCam = _isCam;
+	//this.port = port;
+
+	if(isCam)
+		root = new DefaultMutableTreeNode("camspace");
+	else root = new DefaultMutableTreeNode("worldspace");
 
 	// network setup
 	try {
 		System.out.println("Trying to open socket...");
-		listingSocket = new Socket(host,port);
+		listingSocket = new Socket(host,listingPort);
 		netout = new PrintWriter(listingSocket.getOutputStream(), true);
   		netin = new BufferedReader(new InputStreamReader(
 					listingSocket.getInputStream()));
@@ -194,8 +359,11 @@
 	init();
     }
 
+	
 
     public void init() {
+	enableEvents(AWTEvent.FOCUS_EVENT_MASK);// want to receive FocusEvents
+
 	int strutsize=10;
 	int sepsize=5;
 	getContentPane().setLayout(new BorderLayout());
@@ -203,15 +371,26 @@
 	getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.WEST);
 	getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.EAST);
 		
-	setTitle("TekkotsuMon: Sketch");
-	sketch=new VisionPanel(new VisionListener(host, defSketchPort));
+	setTitle("TekkotsuMon: Sketch/Shape Listing");
+	sketchPanel=new SketchPanel(this, new TCPVisionListener(host, sketchPort), 
+			isCam);
+	sketchPanel.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
+	sketchPanel.setPreferredSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2));
+	sketchPanel.setLockAspectRatio(true);
 	
-	sketch.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
-	sketch.setPreferredSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2));
-	sketch.setLockAspectRatio(true);
-	getContentPane().add(sketch,BorderLayout.CENTER);
+
+	//getContentPane().add(sketch,BorderLayout.NORTH);
+
+	// stuff specific to putting SketchPanel in new frame
+	if (isCam)
+		sketchFrame = new JFrame("Cam Sketch/Shape Frame");
+	else sketchFrame = new JFrame("World Sketch/Shape Frame");
+	sketchFrame.getContentPane().add(sketchPanel);
+	sketchFrame.pack();
+	sketchFrame.show();
 
 	{
+
 	    Box tmp1 = Box.createHorizontalBox();
 	    tmp1.add(Box.createHorizontalStrut(strutsize));
 	    {
@@ -224,17 +403,9 @@
 		    tmp3.add(status=new JLabel(state));
 		    tmp3.add(Box.createHorizontalGlue());
 
-		    spawnBut = new JButton("Spawn New");
-		    spawnBut.setAlignmentX(0.5f);
-		    spawnBut.addActionListener(this);
-		    spawnBut.setActionCommand("spawn");
-		    spawnBut.setEnabled(true);
-		    spawnBut.setToolTipText("Spawns a new sketch monitor;");
-		    tmp3.add(spawnBut);
-
 		    tmp3.add(Box.createHorizontalStrut(strutsize));
 		
-		    refreshBut = new JButton("Refresh Image");
+		    refreshBut = new JButton("Refresh/Scale to Image");
 		    refreshBut.setAlignmentX(0.5f);
 		    refreshBut.addActionListener(this);
 		    refreshBut.setActionCommand("refresh");
@@ -266,13 +437,14 @@
 
 		tmp2.add(Box.createVerticalStrut(strutsize));
 		// Sketch Tree:
-		sketchTree = new JTree(new DefaultTreeModel(initSketchTree(host, port)));
+		sketchTree = new JTree(new DefaultTreeModel(initSketchTree(host, listingPort)));
 		tmp2.add(new JScrollPane(sketchTree));
 		// set up sketch node selection
 		sketchTree.getSelectionModel().setSelectionMode
-		            (TreeSelectionModel.SINGLE_TREE_SELECTION);
+		            (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
 		//Listen for when the selection changes.
 	    sketchTree.addTreeSelectionListener(this);
+		sketchTree.setCellRenderer(new SketchTreeRenderer());
 
 //		JFrame sketchFrame = new JFrame("Sketches");
 //		sketchFrame.setSize(200,400);
@@ -293,60 +465,156 @@
 		tmp1.add(tmp2);
 	    }
 	    tmp1.add(Box.createHorizontalStrut(strutsize));
-	    getContentPane().add(tmp1,BorderLayout.SOUTH);
+	    getContentPane().add(tmp1,BorderLayout.CENTER);
 	}
 	pack();
 	
 	String name="SketchGUI"+".location";
 	setLocation(prefs.getInt(name+".x",50),prefs.getInt(name+".y",50));
+
+	// trigger some beginning events
+//	actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "refreshlist"));
     }
 
     public TreeNode initSketchTree(String host, int port) {
-//	MutableTreeNode root = new DefaultMutableTreeNode("camspace");
 
 	// Just for demonstration:
-	DefaultMutableTreeNode cam = new DefaultMutableTreeNode("cam");
-	DefaultMutableTreeNode pmask = new DefaultMutableTreeNode("pmask");
-	DefaultMutableTreeNode filled = new DefaultMutableTreeNode("filled");
-	DefaultMutableTreeNode skel = new DefaultMutableTreeNode("skel");
-	DefaultMutableTreeNode all_lines = new DefaultMutableTreeNode("all_lines");
-	DefaultMutableTreeNode b_ellipse_render = new DefaultMutableTreeNode("b_ellipse_render");
+	DefaultMutableTreeNode cam = new DefaultMutableTreeNode("hit refresh");
 	root.insert(cam,0);
-	cam.insert(pmask,0);
-	pmask.insert(filled,0);
-	filled.insert(skel,0);
-	skel.insert(all_lines,0);
-	cam.insert(b_ellipse_render,1);
-//	for(int i = 0; i < 5; i++)
-//	     root.insert(new DefaultMutableTreeNode("Sketch("+i+")"), i);
 
 	return root;
     }
 
+	public void sortTree(DefaultMutableTreeNode curNode) {
+		// set up comparator
+		Comparator comp =
+			new Comparator() {
+				public int compare(Object o1, Object o2) {
+					return compare((DefaultMutableTreeNode) o1, (DefaultMutableTreeNode) o2);    
+				}
+				public int compare(DefaultMutableTreeNode n1, DefaultMutableTreeNode n2) {
+					Integer i1 = new Integer(((VisualObjectInfo)n1.getUserObject()).id);
+					Integer i2 = new Integer(((VisualObjectInfo)n2.getUserObject()).id);
+					return i1.compareTo(i2);
+				}
+			};
+
+		// sort the roots children
+		Object[] objs = new Object[curNode.getChildCount()];
+		Enumeration children = curNode.children();
+		for (int i=0;children.hasMoreElements();i++) {
+			DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
+			objs[i] = child;
+		}
+
+		Arrays.sort(objs, comp);
+		curNode.removeAllChildren();
+
+		// insert newly ordered children
+		for (int i=0;i<objs.length;i++) {
+			DefaultMutableTreeNode orderedNode = (DefaultMutableTreeNode) objs[i];
+			curNode.add(orderedNode);
+			if (!orderedNode.isLeaf()) {
+				sortTree(orderedNode);
+			}
+		}
+	}
+
 	// gets called when a Sketch selection is clicked
 	public void valueChanged(TreeSelectionEvent e) {
-		DefaultMutableTreeNode node 
-			= (DefaultMutableTreeNode)sketchTree.getLastSelectedPathComponent();
+		Graphics2D tempgraphics = sketchPanel._image.createGraphics();
+		tempgraphics.setBackground(Color.GRAY);
+		tempgraphics.clearRect(0,0,176,144);
 
-		if (node == null) return;
+		Graphics2D g = sketchPanel._image.createGraphics(); 
 
-//		sketchTree.expandPath(sketchTree.getLeadSelectionPath());
+		TreePath[] paths = sketchTree.getSelectionPaths();
+		if (paths == null) return;
+		for (int path_i = 0; path_i < paths.length; path_i++) {
+			DefaultMutableTreeNode node 
+				=(DefaultMutableTreeNode)(paths[path_i].getLastPathComponent());
 
-		Object nodeInfo = node.getUserObject();
-		if (!node.isRoot()) {
-			SketchInfo sinfo = (SketchInfo)nodeInfo;
-			System.out.println("id clicked:"+sinfo.id);
-			netout.println("get "+sinfo.id);
-			try {
-				String inputLine;
-				while((inputLine=netin.readLine()).compareTo("get end") != 0) {
-					System.out.println(inputLine);
+			if (node == root) continue;	
+			if (node == null) return;
+	
+			VisualObjectInfo vinfo = (VisualObjectInfo)(node.getUserObject());
+			System.out.println(vinfo.toString());
+			if (!node.isRoot()) {
+				System.out.println("id clicked:"+vinfo.id);
+				netout.println("get "+vinfo.id);
+				try {
+					String inputLine;
+					while((inputLine=netin.readLine()).compareTo("get end") != 0) {
+						System.out.println(inputLine);
+					}
+				} catch (IOException ioe) {
+					System.err.println("Transfer error");
 				}
-			} catch (IOException ioe) {
-			System.err.println("Transfer error");
+			} else {
+				//displayURL(helpURL); 
 			}
-		} else {
-			//displayURL(helpURL); 
+		}
+		renderSelectedInTree(g);
+	}
+
+	// called when the window receives focus
+	public void processFocusEvent(FocusEvent e) {
+		System.out.println("received focus");
+		repaint(); // keeps window from getting overwritten; bit of a hack
+	}
+
+	// renders all the currently selected elements in the tree
+	public void renderSelectedInTree(Graphics2D g) {
+		g = sketchPanel._image.createGraphics(); 
+		TreePath[] paths = sketchTree.getSelectionPaths();
+		if (paths == null) return;
+		for (int path_i = 0; path_i < paths.length; path_i++) {
+			DefaultMutableTreeNode node 
+				=(DefaultMutableTreeNode)(paths[path_i].getLastPathComponent());
+
+			if (node == root) continue;	
+			if (node == null) return;
+
+			VisualObjectInfo vinfo = (VisualObjectInfo)(node.getUserObject());
+			int cval = vinfo.getColor();
+			IndexColorModel cmodel = sketchPanel._listener.getColorModel();
+			int rgb = cmodel.getRGB(cval);
+			Color color = new Color(cmodel.getRGB(cval));
+			g.setColor(new Color(cmodel.getRGB(vinfo.getColor())));
+
+			g.setTransform(sketchPanel.resultAtrans);
+			vinfo.renderTo(g);
+		}
+		sketchPanel.repaint();
+		//repaint(); // repaints this frame
+		//paintAll(); // repaints everything in this frame
+	}
+
+	private class SketchTreeRenderer extends DefaultTreeCellRenderer {
+		public SketchTreeRenderer(/*Icon icon*/) {
+//			tutorialIcon = icon;
+		}
+
+		public Component getTreeCellRendererComponent(
+				JTree tree,
+				Object value,
+				boolean sel,
+				boolean expanded,
+				boolean leaf,
+				int row,
+				boolean hasFocus) {
+			super.getTreeCellRendererComponent(
+					tree, value, sel,
+					expanded, leaf, row,
+					hasFocus);
+			try {
+			VisualObjectInfo vinfo = (VisualObjectInfo)(((DefaultMutableTreeNode)value).getUserObject());
+			
+			setIcon(vinfo.getIcon());
+			setToolTipText(vinfo.toString());
+			} catch (ClassCastException e) {}
+
+			return this;
 		}
 	}
 }
Index: tools/mon/org/tekkotsu/mon/SketchInfo.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/SketchInfo.java,v
retrieving revision 1.1
retrieving revision 1.5
diff -u -d -r1.1 -r1.5
--- tools/mon/org/tekkotsu/mon/SketchInfo.java	30 Jan 2004 02:13:10 -0000	1.1
+++ tools/mon/org/tekkotsu/mon/SketchInfo.java	22 Apr 2004 22:46:02 -0000	1.5
@@ -1,24 +1,16 @@
 package org.tekkotsu.mon;
 
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
 
 // stores info for a Sketch, to use as UserObject for DefaultMutableTreeNode
-public class SketchInfo {
-	int id;
-	int parentId;
-	String name;
+public class SketchInfo extends VisualObjectInfo {
+	static Icon icon = new ImageIcon("org/tekkotsu/mon/icons/sketch.png");
 
 	public SketchInfo(int _id, int _parentId, String _name) {
-		id = _id;
-		parentId = _parentId;
-		name = _name;
+		super(_id, _parentId, _name);
 	}
 
-	public int getId() { return id; }
-	public int getParentId() { return parentId; }
-	public String getName() { return name; }
-
-	public String toString() {
-		return (name + "(id " + id + ", parentId " + parentId + ")");
-	}
+	public Icon getIcon() { return icon; }
 }
 
Index: tools/mon/org/tekkotsu/mon/SketchPanel.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/SketchPanel.java,v
retrieving revision 1.1
retrieving revision 1.12
diff -u -d -r1.1 -r1.12
--- tools/mon/org/tekkotsu/mon/SketchPanel.java	30 Jan 2004 02:13:10 -0000	1.1
+++ tools/mon/org/tekkotsu/mon/SketchPanel.java	23 Apr 2004 00:02:53 -0000	1.12
@@ -1,79 +1,99 @@
 package org.tekkotsu.mon;
 
-import java.util.Vector;
-import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+import javax.swing.JLabel;
+import java.awt.Color;
 import java.awt.image.BufferedImage;
+import java.awt.BorderLayout;
 import java.awt.Graphics;
-import java.awt.Color;
-import java.awt.Dimension;
+import java.awt.Graphics2D;
 import java.awt.FontMetrics;
+import java.awt.geom.AffineTransform;
 
-public class SketchPanel extends JPanel {
-    String host;
-    int port;
-    BufferedImage _image;
-    boolean lockAspect=true;
-    Vector sketches;
-    static int width = 176;
-    static int height = 144;
-    float tgtAspect = 176/(float)144;
-
-    protected SketchPanel(String host, int port) {
-	this.host = host;
-	this.port = port;
-	setBackground(Color.BLACK);
-	setForeground(Color.WHITE);
-	setOpaque(!lockAspect);
-	_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+public class SketchPanel extends VisionPanel {
+	SketchGUI gui; // reference back to owning SketchGUI
+	AffineTransform atrans;
+	AffineTransform resultAtrans;
+	boolean isCam;
 
-	// Create a blank frame:
-	update(new Vector());
-    }
+	// coordinate bounds for the view of the SketchPanel
+	float leftBound=0, rightBound=176, topBound=0, bottomBound=144;
 
-    public BufferedImage getImage() {
-	return _image;
-    }
+	protected SketchPanel(SketchGUI _gui, VisionListener listener, 
+			boolean _isCam) {
+		super(listener);
+		gui = _gui;
+		isCam = _isCam;
+		listener.runConnect();
+	}	
+	
+	protected void drawImage(Graphics _g, BufferedImage img, int x, int y, 
+			int w, int h) {
+		Graphics2D g2d = (Graphics2D)_g;
+		float scaling =java.lang.Math.min(img.getWidth()/(rightBound-leftBound),
+				img.getHeight()/(bottomBound-topBound));
+		if(isCam) {
+			atrans = new AffineTransform(1*scaling,0,0,1*scaling,
+					-leftBound*scaling,-topBound*scaling);
+		} else {
+			atrans = new AffineTransform(1*scaling,0,0,-1*scaling,
+					-leftBound*scaling,bottomBound*scaling);
 
-    // Takes in a Vector of int arrays of pixels to composite:
-    public void update(Vector sketches) {
-	int [] data = new int[width*height];
+		}
+		AffineTransform origtrans = g2d.getTransform();
+		g2d.transform(atrans);
+		resultAtrans = g2d.getTransform();
+		//g2d.scale(scale,scale);
+		//g2d.translate(leftBound, topBound);
+//		System.out.println(g2d.getTransform().toString());
+		
+		//buf = new BufferedImage(500,500,BufferedImage.TYPE_BYTE_INDEXED);
+		//buf.setData(img.getRaster());
 
-	// Get new Sketchs and compose them:
-	this.sketches = sketches;
-	for(int i = 0; i < sketches.size(); i++) {
-	    
-	}
-	_image.setRGB(0,0,width,height,data,0,width);
-    }
+		if(img!=null) {
+			g2d.setTransform(origtrans);
+			g2d.drawImage(img,x,y,w,h,null);
+	//		g2d.drawImage(img,x,y,(int)(w*scaling),(int)(h*scaling),null);
+			//g2d.drawImage(img,x,y,null);
+			//g2d.drawImage(img, atrans,null);
+		} else {
+			g2d.setColor(getBackground());
+			g2d.fillRect(x,y,w,h);
+			FontMetrics tmp=g2d.getFontMetrics();
+			String msg="No image";
+			int strw=tmp.stringWidth(msg);
+			int strh=tmp.getHeight();
+			g2d.setColor(getForeground());
+			g2d.drawString(msg,(getSize().width-strw)/2,(getSize().height-strh)/2+tmp.getAscent());
+		}
+	
+		// redraw shapes if necessary
+		gui.renderSelectedInTree(g2d);
 
-    public void paint(Graphics graphics) {
-	super.paint(graphics);
-	Dimension sz=getSize();
+		// draw coordinates
+		if (isCam) {
+		g2d.drawString("("+String.valueOf((int)leftBound)+","
+				+String.valueOf((int)topBound)+")", 0, 10);
+		g2d.drawString("("+String.valueOf((int)rightBound)+","
+				+String.valueOf((int)bottomBound)+")", 145*2, 141*2);
+		} else {
+		g2d.drawString("("+String.valueOf((int)leftBound)+","
+				+String.valueOf((int)bottomBound)+")", 0, 10);
+		g2d.drawString("("+String.valueOf((int)rightBound)+","
+				+String.valueOf((int)topBound)+")", 145*2, 141*2);
+		}
 
-	float curasp=sz.width/(float)sz.height;
-	if(curasp>tgtAspect) {
-	    int width=(int)(sz.height*tgtAspect);
-	    drawImage(graphics,_image, (sz.width-width)/2, 0, width, sz.height);
-	} else if(curasp<tgtAspect) {
-	    int height=(int)(sz.width/tgtAspect);
-	    drawImage(graphics,_image, 0, (sz.height-height)/2, sz.width, height);
-	} else {
-	    drawImage(graphics,_image, 0, 0, sz.width, sz.height);
 	}
-    }
-    
-    protected void drawImage(Graphics g, BufferedImage img, int x, int y, int w, int h) {
-	if(img!=null)
-	     g.drawImage(img,x,y,w,h,null);
-	else {
-	    g.setColor(getBackground());
-	    g.fillRect(x,y,w,h);
-	    FontMetrics tmp=g.getFontMetrics();
-	    String msg="No image";
-	    int strw=tmp.stringWidth(msg);
-	    int strh=tmp.getHeight();
-	    g.setColor(getForeground());
-	    g.drawString(msg,(getSize().width-strw)/2,(getSize().height-strh)/2+tmp.getAscent());
+
+	// stretches the view of the SketchPanel to accomodate the specified object 
+	public void scaleToVisualObject(VisualObjectInfo oinfo) {
+		if(oinfo.getLeft() < leftBound)
+			leftBound = oinfo.getLeft();
+		if(oinfo.getRight() > rightBound)
+			rightBound = oinfo.getRight();
+		if(oinfo.getTop() < topBound)
+			topBound = oinfo.getTop();
+		if(oinfo.getBottom() > bottomBound)
+			bottomBound = oinfo.getBottom();
 	}
-    }
 }
Index: tools/mon/org/tekkotsu/mon/TCPVisionListener.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/TCPVisionListener.java
diff -N tools/mon/org/tekkotsu/mon/TCPVisionListener.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/TCPVisionListener.java	28 Sep 2004 18:56:12 -0000	1.2
@@ -0,0 +1,611 @@
+package org.tekkotsu.mon;
+
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+import java.util.Date;
+
+import java.io.*;
+import java.net.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.IndexColorModel;
+import java.util.Date;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+
+public class TCPVisionListener extends TCPListener implements VisionListener {
+	boolean updatedFlag;
+	Date timestamp;
+	long frameNum=0;
+
+	Vector listeners = new Vector();
+	public void addListener(VisionUpdatedListener l) { listeners.add(l); }
+	public void removeListener(VisionUpdatedListener l) { listeners.remove(l); }
+	public void fireVisionUpdate() {
+		updatedFlag=true;
+		for(int i=0; i<listeners.size(); i++)
+			((VisionUpdatedListener)listeners.get(i)).visionUpdated(this);
+	}
+
+	public Date getTimeStamp() { return timestamp; }
+	public long getFrameNum() { return frameNum; }
+	public IndexColorModel getColorModel() { return cmodel; }
+
+	public boolean hasData() {
+		return updatedFlag;
+	}
+ 
+	public boolean isConnected() {
+		return _isConnected;
+	}
+
+	int channels=3;
+	int width=DEFAULT_WIDTH;
+	int height=DEFAULT_HEIGHT;
+	int pktSize=width*height*channels;
+	int oldformat=PACKET_VISIONRAW_FULL;
+	int format;
+	int compression;
+	int chan_id;
+
+	byte[] _data=new byte[pktSize];
+	byte[] _outd=new byte[pktSize];
+	byte[] _tmp=new byte[pktSize*2];
+	byte[] _jpeg=new byte[pktSize*2];
+	byte[] _newjpeg=new byte[pktSize*2];
+	boolean isJPEG=false;
+	int jpegLen=0;
+	int newjpegLen=0;
+	boolean isIndex=false;
+	boolean badCompressWarn=false;
+	int[] _pixels=new int[width*height];
+	BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+	int bytesRead;
+	boolean convertRGB=true;
+	IndexColorModel cmodel;
+
+	Object packetFormatChangeLock=new Object();
+
+	public boolean hasRawJPEG() { return isJPEG; }
+	public byte[] getJPEG() { return _jpeg; }
+	public int getJPEGLen() { return jpegLen; }
+	
+	public String readLoadSaveString(InputStream in) throws java.io.IOException {
+		int creatorLen=readInt(in);
+		if(!_isConnected) return ""; 
+		String creator=new String(readBytes(in,creatorLen));
+		if(!_isConnected) return "";
+		if(readChar(in)!='\0')
+			System.err.println("Misread LoadSave string? "+creator);
+		return creator;
+	}
+
+	public boolean readChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
+		readBytes(_tmp,in,chanW*chanH);
+		if(!_isConnected) return false;
+		return upsampleData(c,chanW,chanH);
+	}
+	public boolean upsampleData(int c, int chanW, int chanH) {
+		if(chanW==width && chanH==height) {
+			//special case: straight copy if image and channel are same size
+			for(int y=0;y<height;y++) {
+				int datarowstart=y*width*channels+c;
+				int tmprowstart=y*chanW;
+				for(int x=0;x<width;x++)
+					_data[datarowstart+x*channels]=_tmp[tmprowstart+x];
+			}
+			return true;
+		}
+		//otherwise this channel is subsampled, need to blow it up
+		//we'll linearly interpolate between pixels
+		//METHOD A:
+		//hold edges, interpolate through middle:
+		//  if we have 2 samples, scaling up to 4
+		//   index: 0   1    2   3
+		// maps to: 0  1/3  2/3  1
+		/*
+		float xsc=(chanW-1)/(float)(width-1);
+		float ysc=(chanH-1)/(float)(height-1);
+		for(int y=0;y<height-1;y++) {
+			int datarowstart=y*width*channels+c;
+			float ty=y*ysc;
+			int ly=(int)ty; //lower pixel index
+			float fy=ty-ly; //upper pixel weight
+			int tmprowstart=ly*chanW;
+			for(int x=0;x<width-1;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				float uv=((int)_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+			_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
+		}
+		int datarowstart=width*(height-1)*channels+c;
+		int tmprowstart=chanW*(chanH-1);
+		for(int x=0;x<width-1;x++) {
+			float tx=x*xsc;
+			int lx=(int)tx; //lower pixel index
+			float fx=tx-lx; //upper pixel weight
+			_data[datarowstart+x*channels]=(byte)(((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx);
+		}
+		_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
+		*/
+		
+		//Unfortunately, pixels are simply interleaved, starting at the
+		//top right.  So, Method A will stretch things to the bottom-right
+		//a bit.  This method holds left edge and spacing, so it lines up
+		//better with what's being transmitted (but the bottom right edges
+		//wind up smeared)
+		//METHOD B:
+		//  if we have 2 samples, scaling up to 4
+		//   index: 0   1    2   3
+		// maps to: 0  1/2   1   1  <-- this last one would be 3/2, so we have to replicate 1
+		float xsc=(chanW)/(float)(width);
+		float ysc=(chanH)/(float)(height);
+		int xgap=Math.round(1.0f/xsc);
+		int ygap=Math.round(1.0f/ysc);
+		for(int y=0;y<height-ygap;y++) {
+			int datarowstart=y*width*channels+c;
+			float ty=y*ysc;
+			int ly=(int)ty; //lower pixel index
+			float fy=ty-ly; //upper pixel weight
+			int tmprowstart=ly*chanW;
+			for(int x=0;x<width-xgap;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				float uv=(_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+			for(int x=width-xgap;x<width;x++) {
+				float lv=(_tmp[tmprowstart+chanW-1]&0xFF);
+				float uv=(_tmp[tmprowstart+chanW-1+chanW]&0xFF);
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+		}
+		for(int y=height-ygap;y<height;y++) {
+			int datarowstart=y*width*channels+c;
+			int tmprowstart=chanW*(chanH-1);
+			for(int x=0;x<width-xgap;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv);
+			}
+			for(int x=width-xgap;x<width;x++)
+				_data[datarowstart+x*channels]=_tmp[tmprowstart+chanW-1];
+		}
+		
+		return true;
+	}
+
+	public boolean readJPEGChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		newjpegLen=len;
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		if(len>=_newjpeg.length) {
+			System.out.println("Not enough tmp room");
+			return false;
+		}
+		readBytes(_newjpeg,in,len);
+		if(!_isConnected) return false;
+		if(len>chanW*chanH*channels) {
+			if(!badCompressWarn) {
+				badCompressWarn=true;
+				System.out.println("Compressed image is larger than raw would be... :(");
+			}
+		} else {
+			if(badCompressWarn) {
+				badCompressWarn=false;
+				System.out.println("...ok, compressed image is smaller than raw now... :)");
+			}
+		}
+
+		try {
+			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
+			jpegReader.setInput(jpegStream); 
+			Raster decoded=jpegReader.readRaster(0,null);
+			int off=c;
+			for(int y=0; y<chanH; y++)
+				for(int x=0; x<chanW; x++) {
+					_data[off]=(byte)decoded.getSample(x,y,0);
+					off+=channels;
+				}
+		} catch(Exception ex) { ex.printStackTrace(); }
+		return true;
+	}
+
+	public boolean readJPEG(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		newjpegLen=len;
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		if(len>=_newjpeg.length) {
+			System.out.println("Not enough tmp room");
+			return false;
+		}
+		readBytes(_newjpeg,in,len);
+		if(!_isConnected) return false;
+		if(len>chanW*chanH*channels) {
+			if(!badCompressWarn) {
+				badCompressWarn=true;
+				System.out.println("Compressed image is larger than raw would be... :(");
+			}
+		} else {
+			if(badCompressWarn) {
+				badCompressWarn=false;
+				System.out.println("...ok, compressed image is smaller than raw now... :)");
+			}
+		}
+
+		try {
+			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
+			jpegReader.setInput(jpegStream); 
+			Raster decoded=jpegReader.readRaster(0,null);
+			int off=0;
+			for(int y=0; y<chanH; y++)
+				for(int x=0; x<chanW; x++) {
+					_data[off++]=(byte)decoded.getSample(x,y,0);
+					_data[off++]=(byte)decoded.getSample(x,y,2);
+					_data[off++]=(byte)decoded.getSample(x,y,1);
+				}
+		} catch(Exception ex) { ex.printStackTrace(); }
+		return true;
+	}
+
+	byte[] colormap = new byte[256*3];
+	public boolean readColorModel(InputStream in) throws java.io.IOException {
+		int len=readInt(in);
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		readBytes(colormap,in,len*3);
+		if(!_isConnected) return false;
+		//we'll do this stupid thing because we can't change an existing color model, and we don't want to make a new one for each frame
+		// (btw, java is stupid)
+		boolean makeNew=false;
+		if(cmodel==null || len!=cmodel.getMapSize()) {
+			makeNew=true;
+		} else {
+			int off=0;
+			for(int i=0; i<len; i++) {
+				if((byte)cmodel.getRed(i)!=colormap[off++] || (byte)cmodel.getGreen(i)!=colormap[off++] || (byte)cmodel.getBlue(i)!=colormap[off++]) {
+					makeNew=true;
+					break;
+				}
+			}
+		}
+		if(makeNew) {
+			//System.out.println("new color model");
+			cmodel=new IndexColorModel(7,len,colormap,0,false);
+		}
+		return true;
+	}
+	
+	public boolean readIndexedColor(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		readBytes(_data,in,chanW*chanH);
+		if(!_isConnected) return false;
+		if(!readColorModel(in)) return false;
+		if(!_isConnected) return false;
+		isIndex=true;
+		return true;
+	}
+
+	public boolean readRLE(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		if(!_isConnected) return false;
+		readBytes(_tmp,in,len*5);
+		if(!_isConnected) return false;
+
+		int dpos=0;
+		int curx=0, cury=0;
+		for (; len>0 && cury<chanH;) {
+			byte color=_tmp[dpos++];
+			int x=((int)_tmp[dpos++]&0xFF);
+			x|=((int)_tmp[dpos++]&0xFF)<<8;
+			int rlen=((int)_tmp[dpos++]&0xFF);
+			rlen|=((int)_tmp[dpos++]&0xFF)<<8;
+			//System.out.println(color + " "+x + " "+rlen);
+			len--;
+			if (x < curx)
+				return false;
+			
+			for (; curx < x; curx++)
+				_data[cury*width+curx]=0;
+			
+			if (curx+rlen>width)
+				return false;
+			
+			for (; rlen>0; rlen--, curx++)
+				_data[cury*width+curx]=color;
+			if (curx==width) {
+				cury++;
+				curx=0;
+			}
+		}
+		if(!readColorModel(in)) return false;
+		if(!_isConnected) return false;
+		isIndex=true;
+		return true;
+	}
+
+	public void connected(Socket socket) {
+		_isConnected=true;
+		fireVisionUpdate();
+		try {
+			InputStream in=socket.getInputStream();
+			_isConnected=true;
+			while (true) {
+				String type = readLoadSaveString(in);
+				if(!_isConnected) break; //System.out.println("Got type="+type);
+				if(!type.equals("TekkotsuImage")) {
+					System.err.println("Unrecognized type: "+type);
+					break;
+				}
+				format=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got format="+format);
+				compression=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got compression="+compression);
+				int newWidth=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got newWidth="+newWidth);
+				int newHeight=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got newHeight="+newHeight);
+				long timest=readInt(in);
+				if(timest<0)
+					timest+=(1L<<32);
+				if(!_isConnected) break; //System.out.println("Got timest="+timest);
+				frameNum=readInt(in);
+				if(frameNum<0)
+					frameNum+=(1L<<32);
+				if(!_isConnected) break; //System.out.println("Got frameNum="+frameNum);
+				
+				if (format!=oldformat || newWidth!=width || newHeight!=height) {
+					width=newWidth;
+					height=newHeight;
+					synchronized (packetFormatChangeLock) {
+						switch (format) {
+						case ENCODE_COLOR:
+							channels=3;
+							pktSize=width*height*channels;
+							break;
+						case ENCODE_SINGLE_CHANNEL:
+							channels=1;
+							pktSize=width*height*channels;
+							break;
+						default:
+							System.err.println("VisionRawListener: unknown packet type "+format);
+							throw new java.lang.NoSuchFieldException("fake exception");
+						}
+						_data=new byte[pktSize];
+						_outd=new byte[pktSize];
+						_tmp=new byte[pktSize];
+						_jpeg=new byte[pktSize*2<2000?2000:pktSize*2];
+						_newjpeg=new byte[pktSize*2<2000?2000:pktSize*2];
+						_pixels=new int[width*height];;
+						img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+						oldformat=format;
+					}
+				}
+				
+				boolean failed=false;
+				for(int i=0; i<channels; i++) {
+					String creator = readLoadSaveString(in);
+					if(!_isConnected) break; //System.out.println("Got creator="+creator);
+					if(!creator.equals("FbkImage")) {
+						System.err.println("Unrecognized creator: "+creator);
+						failed=true; break;
+					} else {
+						int chanwidth=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chanwidth="+chanwidth);
+						int chanheight=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chanheight="+chanheight);
+						
+						if(chanwidth>width || chanheight>height) {
+							System.err.println("channel dimensions exceed image dimensions");
+							failed=true; break;
+						}
+						
+						int layer=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got layer="+layer);
+						chan_id=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chan_id="+chan_id);
+				
+						String fmt=readLoadSaveString(in);
+						if(!_isConnected) break; //System.out.println("Got fmt="+fmt);
+						if(fmt.equals("blank")) {
+							isJPEG=false;
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							int off=useChan;
+							for(int y=0; y<height; y++)
+								for(int x=0; x<width; x++) {
+									_data[off]=(byte)(convertRGB?0x80:0);
+									off+=channels;
+								}
+						} else if(fmt.equals("RawImage")) {
+							isJPEG=false;
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							if(!readChannel(in,useChan,chanwidth,chanheight)) { failed=true; break; }
+						} else if(fmt.equals("JPEGGrayscale")) {
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							if(!readJPEGChannel(in,useChan,chanwidth,chanheight)) { failed=true; break; }
+							isJPEG=(channels==1);
+						} else if(fmt.equals("JPEGColor")) {
+							isIndex=false;
+							if(format==ENCODE_SINGLE_CHANNEL)
+								System.err.println("WTF? ");
+							if(!readJPEG(in,chanwidth,chanheight)) { failed=true; break; }
+							i=channels;
+							isJPEG=true;
+						} else if(fmt.equals("SegColorImage")) {
+							isJPEG=false;
+							isIndex=true;
+							if(!readIndexedColor(in,chanwidth,chanheight)) { failed=true; break; }
+						} else if(fmt.equals("RLEImage")) {
+							isJPEG=false;
+							isIndex=true;
+							if(!readRLE(in,chanwidth,chanheight)) { failed=true; break; }
+						} else {
+							isJPEG=false;
+							isIndex=false;
+							System.err.println("Unrecognized format: "+fmt);
+							failed=true; break;
+						}
+					}
+				}
+				if(failed || !_isConnected)
+					break;
+				
+				synchronized(_outd) {
+					byte[] temp=_data;
+					_data=_outd;
+					_outd=temp;
+					if(isJPEG) {
+						temp=_newjpeg;
+						_newjpeg=_jpeg;
+						_jpeg=temp;
+						int tempi=newjpegLen;
+						newjpegLen=jpegLen;
+						jpegLen=tempi;
+						updatedFlag = true;
+					}
+					timestamp=new Date(timest);
+				}
+				fireVisionUpdate();
+			}
+		} catch (Exception ex) { }
+		
+		try { socket.close(); } catch (Exception ex) { }
+		_isConnected=false;
+		fireVisionUpdate();
+	}
+	
+	public byte[] getData() {
+//		frameTimer();
+		synchronized (_outd) {
+			updatedFlag=false;
+			return _outd;
+		}
+	}
+
+	public void setConvertRGB(boolean b) { 
+		if(b!=convertRGB) {
+			convertRGB=b;
+			updatedFlag=true;
+		}
+	}
+	public boolean getConvertRGB() { return convertRGB; }
+
+	public int[] getYUVPixels() {
+		synchronized(packetFormatChangeLock) {
+			byte[] data=getData();
+			int offset=0;
+			for (int i=0; i<width*height; i++) {
+				int y=(int)data[offset++]&0xFF;
+				int u=(int)data[offset++]&0xFF;
+				int v=(int)data[offset++]&0xFF;
+				_pixels[i]=(255<<24) | (y<<16) | (u<<8) | v;
+			}
+		}
+		return _pixels;
+	}
+
+	//This still uses RGB pixels just in case you want to display the
+	//intensity value into hues instead of black/white
+	public int[] getIntensityPixels() {
+		synchronized(packetFormatChangeLock) {
+			byte[] data=getData();
+			int offset=0;
+			if(!getConvertRGB()) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=(255<<24) | (z<<16) | (z<<8) | z;
+				}
+			} else if(chan_id==CHAN_Y || chan_id==CHAN_Y_DY || chan_id==CHAN_Y_DX || chan_id==CHAN_Y_DXDY ) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(z,0x80,0x80);
+				}
+			} else if(chan_id==CHAN_U) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(0x80,z,0x80);
+				}
+			} else if(chan_id==CHAN_V) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(0x80,0x80,z);
+				}
+			}
+		}		
+		return _pixels;
+	}
+
+	public int[] getRGBPixels() {
+		synchronized(packetFormatChangeLock) {
+			byte[] data=getData();
+			int offset=0;
+			for (int i=0; i<width*height; i++) {
+				int y=(int)data[offset++]&0xFF;
+				int u=(int)data[offset++]&0xFF;
+				int v=(int)data[offset++]&0xFF;
+				_pixels[i]=pixelYUV2RGB(y, u, v);
+			}
+		}
+		return _pixels;
+	}
+
+	static final int pixelYUV2RGB(int y, int u, int v) {
+		u=u*2-255;
+		v=v*2-255;
+		int r=y+u;
+		int b=y+v;
+		u=u>>1;
+		v=(v>>2)-(v>>4);
+		int g=y-u-v;
+		if (r<0) r=0; if (g<0) g=0; if (b<0) b=0;
+		if (r>255) r=255; if (g>255) g=255; if (b>255) b=255;
+
+		return (255<<24) | (r<<16) | (g<<8) | b;
+	}
+
+	public BufferedImage getImage() {
+		if(!updatedFlag)
+			return img;
+		if(isIndex) {
+			byte[] data=getData();
+			if(cmodel==null)
+				return img;
+			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
+				img=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_INDEXED,cmodel);
+			img.getRaster().setDataElements(0,0,width,height,data);
+		} else {
+			int[] pix;
+			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
+				img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+			if(format==ENCODE_COLOR)
+				pix=getConvertRGB()?getRGBPixels():getYUVPixels();
+			else
+				pix=getIntensityPixels();
+			img.setRGB(0,0,width,height,pix,0,width);
+		}
+		return img;
+	}
+
+
+
+	public TCPVisionListener() { super(); }
+	public TCPVisionListener(int port) { super(port); }
+	public TCPVisionListener(String host, int port) { super(host,port); }
+}
Index: tools/mon/org/tekkotsu/mon/UDPListener.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/UDPListener.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tools/mon/org/tekkotsu/mon/UDPListener.java	2 Oct 2003 02:08:08 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/UDPListener.java	27 Sep 2004 22:48:36 -0000	1.3
@@ -1,32 +1,67 @@
-package org.tekkotsu.mon;
-
-import java.net.DatagramSocket;
-
-public abstract class UDPListener extends Listener {
-  public abstract void connected(DatagramSocket socket);
-
-  public void runServer() {
-    try {
-      _socket=new DatagramSocket(_port);
-      connected(_socket);
-    } catch (Exception ex) {
-      System.out.println("port "+_port+": "+ex);
-    }
-  }
-
-  public void runConnect() {
-    try {
-      _socket=new DatagramSocket();
-      connected(_socket);
-    } catch (Exception ex) { }
-  }
-
-  public void close() {
-  }
-
-  public UDPListener() { super(); }
-  public UDPListener(int port) { super(port); }
-  public UDPListener(String host, int port) { super(host, port); }
-
-  DatagramSocket _socket;
-}
+package org.tekkotsu.mon;
+
+import java.net.DatagramSocket;
+import java.net.*;
+
+
+public abstract class UDPListener extends Listener {
+  public abstract void connected(DatagramSocket socket);
+
+  String message = new String("connection request");
+  byte[] buf = message.getBytes();
+
+  public void runServer() {
+    try {
+      _socket=new DatagramSocket(_port);
+
+      try {
+        _socket.connect(InetAddress.getByName(_host), _port);
+        _socket.setSoTimeout(2000); // block for 2 seconds at most
+      } catch (Exception ex) { }
+
+      // send a dummy message so that the AIBO can see what
+      // address to connect it's UDP socket to
+      DatagramPacket message = new DatagramPacket(buf, buf.length,
+                                                  InetAddress.getByName(_host),
+                                                  _port);
+      _socket.send(message);
+
+      connected(_socket);
+    } catch (Exception ex) {
+      System.out.println("port "+_port+": "+ex);
+    }
+  }
+
+  public void runConnect() {
+    try {
+      _socket=new DatagramSocket(_port);
+
+      try {
+        _socket.connect(InetAddress.getByName(_host), _port);
+        _socket.setSoTimeout(2000); // block for 2 seconds at most
+      } catch (Exception ex) { }
+
+      // send a dummy message so that the AIBO can see what
+      // address to connect it's UDP socket to
+      DatagramPacket message = new DatagramPacket(buf, buf.length,
+                                                  InetAddress.getByName(_host),
+                                                  _port);
+      _socket.send(message);
+
+      connected(_socket);
+    } catch (Exception ex) { }
+  }
+
+  public void close() {
+
+	try{_socket.close();}
+	catch(Exception e){}
+
+  }
+
+  public UDPListener() { super(); }
+  public UDPListener(int port) { super(port); }
+  public UDPListener(String host, int port) { super(host, port); }
+
+  DatagramSocket _socket;
+}
Index: tools/mon/org/tekkotsu/mon/UDPVisionListener.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/UDPVisionListener.java
diff -N tools/mon/org/tekkotsu/mon/UDPVisionListener.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/UDPVisionListener.java	28 Sep 2004 22:12:38 -0000	1.3
@@ -0,0 +1,617 @@
+package org.tekkotsu.mon;
+
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+import java.util.Date;
+
+import java.io.*;
+import java.net.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.IndexColorModel;
+import java.util.Date;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+
+public class UDPVisionListener extends UDPListener implements VisionListener {
+  DatagramSocket mysock;
+	
+  byte[] buf = new byte[200000];
+  DatagramPacket incoming = new DatagramPacket(buf, buf.length);
+	
+  InputStream in;
+
+	boolean updatedFlag;
+	Date timestamp;
+	long frameNum=0;
+
+	Vector listeners = new Vector();
+	public void addListener(VisionUpdatedListener l) { listeners.add(l); }
+	public void removeListener(VisionUpdatedListener l) { listeners.remove(l); }
+	public void fireVisionUpdate() {
+		updatedFlag=true;
+		for(int i=0; i<listeners.size(); i++)
+			((VisionUpdatedListener)listeners.get(i)).visionUpdated(this);
+	}
+
+	public Date getTimeStamp() { return timestamp; }
+	public long getFrameNum() { return frameNum; }
+	public IndexColorModel getColorModel() { return cmodel; }
+
+	public boolean hasData() {
+		return updatedFlag;
+	}
+ 
+	public boolean isConnected() {
+		return _isConnected;
+	}
+
+	int channels=3;
+	int width=DEFAULT_WIDTH;
+	int height=DEFAULT_HEIGHT;
+	int pktSize=width*height*channels;
+	int oldformat=PACKET_VISIONRAW_FULL;
+	int format;
+	int compression;
+	int chan_id;
+
+	byte[] _data=new byte[pktSize];
+	byte[] _outd=new byte[pktSize];
+	byte[] _tmp=new byte[pktSize*2];
+	byte[] _jpeg=new byte[pktSize*2];
+	byte[] _newjpeg=new byte[pktSize*2];
+	boolean isJPEG=false;
+	int jpegLen=0;
+	int newjpegLen=0;
+	boolean isIndex=false;
+	boolean badCompressWarn=false;
+	int[] _pixels=new int[width*height];
+	BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+	int bytesRead;
+	boolean convertRGB=true;
+	IndexColorModel cmodel;
+
+	public boolean hasRawJPEG() { return isJPEG; }
+	public byte[] getJPEG() { return _jpeg; }
+	public int getJPEGLen() { return jpegLen; }
+	
+	public String readLoadSaveString(InputStream in) throws java.io.IOException {
+		int creatorLen=readInt(in);
+		if(!_isConnected) return ""; 
+		String creator=new String(readBytes(in,creatorLen));
+		if(!_isConnected) return "";
+		if(readChar(in)!='\0')
+			System.err.println("Misread LoadSave string? "+creator);
+		return creator;
+	}
+
+	public boolean readChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
+		readBytes(_tmp,in,chanW*chanH);
+		if(!_isConnected) return false;
+		return upsampleData(c,chanW,chanH);
+	}
+	public boolean upsampleData(int c, int chanW, int chanH) {
+		if(chanW==width && chanH==height) {
+			//special case: straight copy if image and channel are same size
+			for(int y=0;y<height;y++) {
+				int datarowstart=y*width*channels+c;
+				int tmprowstart=y*chanW;
+				for(int x=0;x<width;x++)
+					_data[datarowstart+x*channels]=_tmp[tmprowstart+x];
+			}
+			return true;
+		}
+		//otherwise this channel is subsampled, need to blow it up
+		//we'll linearly interpolate between pixels
+		//METHOD A:
+		//hold edges, interpolate through middle:
+		//  if we have 2 samples, scaling up to 4
+		//   index: 0   1    2   3
+		// maps to: 0  1/3  2/3  1
+		/*
+		float xsc=(chanW-1)/(float)(width-1);
+		float ysc=(chanH-1)/(float)(height-1);
+		for(int y=0;y<height-1;y++) {
+			int datarowstart=y*width*channels+c;
+			float ty=y*ysc;
+			int ly=(int)ty; //lower pixel index
+			float fy=ty-ly; //upper pixel weight
+			int tmprowstart=ly*chanW;
+			for(int x=0;x<width-1;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				float uv=((int)_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+			_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
+		}
+		int datarowstart=width*(height-1)*channels+c;
+		int tmprowstart=chanW*(chanH-1);
+		for(int x=0;x<width-1;x++) {
+			float tx=x*xsc;
+			int lx=(int)tx; //lower pixel index
+			float fx=tx-lx; //upper pixel weight
+			_data[datarowstart+x*channels]=(byte)(((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx);
+		}
+		_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
+		*/
+		
+		//Unfortunately, pixels are simply interleaved, starting at the
+		//top right.  So, Method A will stretch things to the bottom-right
+		//a bit.  This method holds left edge and spacing, so it lines up
+		//better with what's being transmitted (but the bottom right edges
+		//wind up smeared)
+		//METHOD B:
+		//  if we have 2 samples, scaling up to 4
+		//   index: 0   1    2   3
+		// maps to: 0  1/2   1   1  <-- this last one would be 3/2, so we have to replicate 1
+		float xsc=(chanW)/(float)(width);
+		float ysc=(chanH)/(float)(height);
+		int xgap=Math.round(1.0f/xsc);
+		int ygap=Math.round(1.0f/ysc);
+		for(int y=0;y<height-ygap;y++) {
+			int datarowstart=y*width*channels+c;
+			float ty=y*ysc;
+			int ly=(int)ty; //lower pixel index
+			float fy=ty-ly; //upper pixel weight
+			int tmprowstart=ly*chanW;
+			for(int x=0;x<width-xgap;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				float uv=(_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+			for(int x=width-xgap;x<width;x++) {
+				float lv=(_tmp[tmprowstart+chanW-1]&0xFF);
+				float uv=(_tmp[tmprowstart+chanW-1+chanW]&0xFF);
+				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
+			}
+		}
+		for(int y=height-ygap;y<height;y++) {
+			int datarowstart=y*width*channels+c;
+			int tmprowstart=chanW*(chanH-1);
+			for(int x=0;x<width-xgap;x++) {
+				float tx=x*xsc;
+				int lx=(int)tx; //lower pixel index
+				float fx=tx-lx; //upper pixel weight
+
+				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
+				_data[datarowstart+x*channels]=(byte)(lv);
+			}
+			for(int x=width-xgap;x<width;x++)
+				_data[datarowstart+x*channels]=_tmp[tmprowstart+chanW-1];
+		}
+		
+		return true;
+	}
+
+	public boolean readJPEGChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		newjpegLen=len;
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		if(len>=_newjpeg.length) {
+			System.out.println("Not enough tmp room");
+			return false;
+		}
+		readBytes(_newjpeg,in,len);
+		if(!_isConnected) return false;
+		if(len>chanW*chanH*channels) {
+			if(!badCompressWarn) {
+				badCompressWarn=true;
+				System.out.println("Compressed image is larger than raw would be... :(");
+			}
+		} else {
+			if(badCompressWarn) {
+				badCompressWarn=false;
+				System.out.println("...ok, compressed image is smaller than raw now... :)");
+			}
+		}
+
+		try {
+			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
+			jpegReader.setInput(jpegStream); 
+			Raster decoded=jpegReader.readRaster(0,null);
+			int off=c;
+			for(int y=0; y<chanH; y++)
+				for(int x=0; x<chanW; x++) {
+					_data[off]=(byte)decoded.getSample(x,y,0);
+					off+=channels;
+				}
+		} catch(Exception ex) { ex.printStackTrace(); }
+		return true;
+	}
+
+	public boolean readJPEG(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		newjpegLen=len;
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		if(len>=_newjpeg.length) {
+			System.out.println("Not enough tmp room");
+			return false;
+		}
+		readBytes(_newjpeg,in,len);
+		if(!_isConnected) return false;
+		if(len>chanW*chanH*channels) {
+			if(!badCompressWarn) {
+				badCompressWarn=true;
+				System.out.println("Compressed image is larger than raw would be... :(");
+			}
+		} else {
+			if(badCompressWarn) {
+				badCompressWarn=false;
+				System.out.println("...ok, compressed image is smaller than raw now... :)");
+			}
+		}
+
+		try {
+			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
+			jpegReader.setInput(jpegStream); 
+			Raster decoded=jpegReader.readRaster(0,null);
+			int off=0;
+			for(int y=0; y<chanH; y++)
+				for(int x=0; x<chanW; x++) {
+					_data[off++]=(byte)decoded.getSample(x,y,0);
+					_data[off++]=(byte)decoded.getSample(x,y,2);
+					_data[off++]=(byte)decoded.getSample(x,y,1);
+				}
+		} catch(Exception ex) { ex.printStackTrace(); }
+		return true;
+	}
+
+	byte[] colormap = new byte[256*3];
+	public boolean readColorModel(InputStream in) throws java.io.IOException {
+		int len=readInt(in);
+		//System.out.println("len="+len);
+		if(!_isConnected) return false;
+		readBytes(colormap,in,len*3);
+		if(!_isConnected) return false;
+		//we'll do this stupid thing because we can't change an existing color model, and we don't want to make a new one for each frame
+		// (btw, java is stupid)
+		boolean makeNew=false;
+		if(cmodel==null || len!=cmodel.getMapSize()) {
+			makeNew=true;
+		} else {
+			int off=0;
+			for(int i=0; i<len; i++) {
+				if((byte)cmodel.getRed(i)!=colormap[off++] || (byte)cmodel.getGreen(i)!=colormap[off++] || (byte)cmodel.getBlue(i)!=colormap[off++]) {
+					makeNew=true;
+					break;
+				}
+			}
+		}
+		if(makeNew) {
+			//System.out.println("new color model");
+			cmodel=new IndexColorModel(7,len,colormap,0,false);
+		}
+		return true;
+	}
+	
+	public boolean readIndexedColor(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		readBytes(_data,in,chanW*chanH);
+		if(!_isConnected) return false;
+		if(!readColorModel(in)) return false;
+		if(!_isConnected) return false;
+		isIndex=true;
+		return true;
+	}
+
+	public boolean readRLE(InputStream in, int chanW, int chanH) throws java.io.IOException {
+		int len=readInt(in);
+		if(!_isConnected) return false;
+		readBytes(_tmp,in,len*5);
+		if(!_isConnected) return false;
+
+		int dpos=0;
+		int curx=0, cury=0;
+		for (; len>0 && cury<chanH;) {
+			byte color=_tmp[dpos++];
+			int x=((int)_tmp[dpos++]&0xFF);
+			x|=((int)_tmp[dpos++]&0xFF)<<8;
+			int rlen=((int)_tmp[dpos++]&0xFF);
+			rlen|=((int)_tmp[dpos++]&0xFF)<<8;
+			//System.out.println(color + " "+x + " "+rlen);
+			len--;
+			if (x < curx)
+				return false;
+			
+			for (; curx < x; curx++)
+				_data[cury*width+curx]=0;
+			
+			if (curx+rlen>width)
+				return false;
+			
+			for (; rlen>0; rlen--, curx++)
+				_data[cury*width+curx]=color;
+			if (curx==width) {
+				cury++;
+				curx=0;
+			}
+		}
+		if(!readColorModel(in)) return false;
+		if(!_isConnected) return false;
+		isIndex=true;
+		return true;
+	}
+
+	public void connected(DatagramSocket UDPsocket) {
+		_isConnected=true;
+		fireVisionUpdate();
+		mysock = UDPsocket;
+		_isConnected=true;
+		try {
+			while(!mysock.isClosed()) {
+				mysock.receive(incoming);
+				in = new ByteArrayInputStream(incoming.getData());
+				String type = readLoadSaveString(in);
+				if(!_isConnected) break; //System.out.println("Got type="+type);
+				if(!type.equals("TekkotsuImage")) {
+					System.err.println("Unrecognized type: "+type);
+					break;
+				}
+				format=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got format="+format);
+				compression=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got compression="+compression);
+				int newWidth=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got newWidth="+newWidth);
+				int newHeight=readInt(in);
+				if(!_isConnected) break; //System.out.println("Got newHeight="+newHeight);
+				long timest=readInt(in);
+				if(timest<0)
+					timest+=(1L<<32);
+				if(!_isConnected) break; //System.out.println("Got timest="+timest);
+				frameNum=readInt(in);
+				if(frameNum<0)
+					frameNum+=(1L<<32);
+				if(!_isConnected) break; //System.out.println("Got frameNum="+frameNum);
+				
+				if (format!=oldformat || newWidth!=width || newHeight!=height) {
+					width=newWidth;
+					height=newHeight;
+					synchronized (_outd) {
+						switch (format) {
+						case ENCODE_COLOR:
+							channels=3;
+							pktSize=width*height*channels;
+							break;
+						case ENCODE_SINGLE_CHANNEL:
+							channels=1;
+							pktSize=width*height*channels;
+							break;
+						default:
+							System.err.println("VisionRawListener: unknown packet type "+format);
+							throw new java.lang.NoSuchFieldException("fake exception");
+						}
+						_data=new byte[pktSize];
+						_outd=new byte[pktSize];
+						_tmp=new byte[pktSize];
+						_jpeg=new byte[pktSize*2<2000?2000:pktSize*2];
+						_newjpeg=new byte[pktSize*2<2000?2000:pktSize*2];
+						_pixels=new int[width*height];;
+						img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+						oldformat=format;
+					}
+				}
+				
+				boolean failed=false;
+				for(int i=0; i<channels; i++) {
+					String creator = readLoadSaveString(in);
+					if(!_isConnected) break; //System.out.println("Got creator="+creator);
+					if(!creator.equals("FbkImage")) {
+						System.err.println("Unrecognized creator: "+creator);
+						failed=true; break;
+					} else {
+						int chanwidth=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chanwidth="+chanwidth);
+						int chanheight=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chanheight="+chanheight);
+						
+						if(chanwidth>width || chanheight>height) {
+							System.err.println("channel dimensions exceed image dimensions");
+							failed=true; break;
+						}
+						
+						int layer=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got layer="+layer);
+						chan_id=readInt(in);
+						if(!_isConnected) break; //System.out.println("Got chan_id="+chan_id);
+				
+						String fmt=readLoadSaveString(in);
+						if(!_isConnected) break; //System.out.println("Got fmt="+fmt);
+						if(fmt.equals("blank")) {
+							isJPEG=false;
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							int off=useChan;
+							for(int y=0; y<height; y++)
+								for(int x=0; x<width; x++) {
+									_data[off]=(byte)(convertRGB?0x80:0);
+									off+=channels;
+								}
+						} else if(fmt.equals("RawImage")) {
+							isJPEG=false;
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							if(!readChannel(in,useChan,chanwidth,chanheight)) { failed=true; System.err.println("UDPVisionListener channel read failed"); break; }
+						} else if(fmt.equals("JPEGGrayscale")) {
+							isIndex=false;
+							int useChan=(channels==1)?i:chan_id;
+							if(!readJPEGChannel(in,useChan,chanwidth,chanheight)) { failed=true; System.err.println("UDPVisionListener JPEGGreyscale channel read failed"); break; }
+							isJPEG=(channels==1);
+						} else if(fmt.equals("JPEGColor")) {
+							isIndex=false;
+							if(format==ENCODE_SINGLE_CHANNEL)
+								System.err.println("WTF? ");
+							if(!readJPEG(in,chanwidth,chanheight)) { failed=true; System.err.println("UDPVisionListener JPEGColor channel read failed"); break; }
+							i=channels;
+							isJPEG=true;
+						} else if(fmt.equals("SegColorImage")) {
+							isJPEG=false;
+							isIndex=true;
+							if(!readIndexedColor(in,chanwidth,chanheight)) { failed=true; System.err.println("UDPVisionListener SegColor read failed"); break; }
+						} else if(fmt.equals("RLEImage")) {
+							isJPEG=false;
+							isIndex=true;
+							if(!readRLE(in,chanwidth,chanheight)) { failed=true; System.err.println("UDPVisionListener RLEImage read failed"); break; }
+						} else {
+							isJPEG=false;
+							isIndex=false;
+							System.err.println("Unrecognized format: "+fmt);
+							failed=true; break;
+						}
+					}
+				}
+				if(failed || !_isConnected) {
+					System.err.println("UDPVisionListener connection lost");
+					break;
+				}
+				
+				synchronized(_outd) {
+					byte[] temp=_data;
+					_data=_outd;
+					_outd=temp;
+					if(isJPEG) {
+						temp=_newjpeg;
+						_newjpeg=_jpeg;
+						_jpeg=temp;
+						int tempi=newjpegLen;
+						newjpegLen=jpegLen;
+						jpegLen=tempi;
+						updatedFlag = true;
+					}
+					timestamp=new Date(timest);
+				}
+				fireVisionUpdate();
+			}
+		} catch (Exception ex) { }
+		
+		_isConnected=false;
+	}
+	
+	public byte[] getData() {
+		synchronized (_outd) {
+			updatedFlag=false;
+			return _outd;
+		}
+	}
+
+	public void setConvertRGB(boolean b) { 
+		if(b!=convertRGB) {
+			convertRGB=b;
+			updatedFlag=true;
+		}
+	}
+	public boolean getConvertRGB() { return convertRGB; }
+
+	public int[] getYUVPixels() {
+		synchronized(_outd) {
+			byte[] data=getData();
+			int offset=0;
+			for (int i=0; i<width*height; i++) {
+				int y=(int)data[offset++]&0xFF;
+				int u=(int)data[offset++]&0xFF;
+				int v=(int)data[offset++]&0xFF;
+				_pixels[i]=(255<<24) | (y<<16) | (u<<8) | v;
+			}
+		}
+		return _pixels;
+	}
+
+	//This still uses RGB pixels just in case you want to display the
+	//intensity value into hues instead of black/white
+	public int[] getIntensityPixels() {
+		synchronized(_outd) {
+			byte[] data=getData();
+			int offset=0;
+			if(!getConvertRGB()) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=(255<<24) | (z<<16) | (z<<8) | z;
+				}
+			} else if(chan_id==CHAN_Y || chan_id==CHAN_Y_DY || chan_id==CHAN_Y_DX || chan_id==CHAN_Y_DXDY ) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(z,0x80,0x80);
+				}
+			} else if(chan_id==CHAN_U) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(0x80,z,0x80);
+				}
+			} else if(chan_id==CHAN_V) {
+				for (int i=0; i<width*height; i++) {
+					int z=(int)data[offset++]&0xFF;
+					_pixels[i]=pixelYUV2RGB(0x80,0x80,z);
+				}
+			}
+		}		
+		return _pixels;
+	}
+
+	public int[] getRGBPixels() {
+		synchronized(_outd) {
+			byte[] data=getData();
+			int offset=0;
+			for (int i=0; i<width*height; i++) {
+				int y=(int)data[offset++]&0xFF;
+				int u=(int)data[offset++]&0xFF;
+				int v=(int)data[offset++]&0xFF;
+				_pixels[i]=pixelYUV2RGB(y, u, v);
+			}
+		}
+		return _pixels;
+	}
+
+	static final int pixelYUV2RGB(int y, int u, int v) {
+		u=u*2-255;
+		v=v*2-255;
+		int r=y+u;
+		int b=y+v;
+		u=u>>1;
+		v=(v>>2)-(v>>4);
+		int g=y-u-v;
+		if (r<0) r=0; if (g<0) g=0; if (b<0) b=0;
+		if (r>255) r=255; if (g>255) g=255; if (b>255) b=255;
+
+		return (255<<24) | (r<<16) | (g<<8) | b;
+	}
+
+	public BufferedImage getImage() {
+		if(!updatedFlag)
+			return img;
+		if(isIndex) {
+			byte[] data=getData();
+			if(cmodel==null)
+				return img;
+			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
+				img=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_INDEXED,cmodel);
+			img.getRaster().setDataElements(0,0,width,height,data);
+		} else {
+			int[] pix;
+			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
+				img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+			if(format==ENCODE_COLOR)
+				pix=getConvertRGB()?getRGBPixels():getYUVPixels();
+			else
+				pix=getIntensityPixels();
+			img.setRGB(0,0,width,height,pix,0,width);
+		}
+		return img;
+	}
+
+
+
+	public UDPVisionListener() { super(); }
+	public UDPVisionListener(int port) { super(port); }
+	public UDPVisionListener(String host, int port) { super(host,port); }
+}
Index: tools/mon/org/tekkotsu/mon/VisionGUI.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java,v
retrieving revision 1.12
retrieving revision 1.14
diff -u -d -r1.12 -r1.14
--- tools/mon/org/tekkotsu/mon/VisionGUI.java	5 Feb 2004 19:12:31 -0000	1.12
+++ tools/mon/org/tekkotsu/mon/VisionGUI.java	28 Sep 2004 18:56:12 -0000	1.14
@@ -81,41 +81,15 @@
 	public static void main(String s[]) {
 		int port=-1;
 		if(s.length<2)
-			usage();
-		String[] args=new String[1];
-		if(s[1].toUpperCase().compareTo("RLE")==0) {
-			args[0]=s[1];
-			port=VisionListener.defRLEPort;
-		} else if(s[1].toUpperCase().compareTo("RAW")==0) {
-			args[0]=s[1];
-			port=VisionListener.defRawPort;
-		} else {
-			port=Integer.parseInt(s[1]);
-		}
-		if(s.length>2) {
-			args[0]=s[2];
-			if(s[2].toUpperCase().compareTo("RLE")==0)
-				port=VisionListener.defRLEPort;
-			else if(s[2].toUpperCase().compareTo("RAW")==0)
-				port=VisionListener.defRawPort;
-		}
-		VisionGUI gui;
-		if(args[0].length()==0)
-			gui=new VisionGUI(s[0],port,new String[0]);
-		else
-			gui=new VisionGUI(s[0],port,args);
+			VisionPanel.usage();
+		String[] args=new String[s.length-1];
+		for(int i=0; i<args.length; i++)
+			args[i]=s[i+1];
+		VisionGUI gui=new VisionGUI(s[0],args);
 		gui.addWindowListener(new WindowAdapter() {
 				public void windowClosing(WindowEvent e) { System.exit(0); } });
 	}
-		
-	public static void usage() {
-		System.out.println("Usage: java VisionGUI host [port|raw|rle]");
-		System.out.println("       if port is not specified, it defaults to:");
-		System.out.println("       "+VisionListener.defRawPort+" for raw");
-		System.out.println("       "+VisionListener.defRLEPort+" for RLE.");
-		System.exit(2);
-	}
-			
+				
 	public void actionPerformed(ActionEvent e) {
 		if(e.getActionCommand().compareTo("YUV")==0) {
 			vision.setConvertRGB(false);
@@ -283,62 +257,33 @@
 	
 	public VisionGUI(String host, String[] args) {
 		super();
-		int port=-1;
-		for(int i=0; i<args.length; i++) {
-			if(args[i].toUpperCase().compareTo("RLE")==0) {
-				isRLE=true;
-				isRaw=false;
-			} else if(args[i].toUpperCase().compareTo("RAW")==0) {
-				isRaw=true;
-				isRLE=false;
-			} else
-				System.err.println("VisionGUI: Unrecognized argument: "+args[0]);
-		}
-		if(isRLE)
-			port=VisionListener.defRLEPort;
-		else if(isRaw)
-			port=VisionListener.defRawPort;
-		init(host,port,args);
+		init(host,args);
 	}
 	public VisionGUI(String host, int port, String[] args) {
 		super();
-		init(host,port,args);
+		String[] passargs=new String[args.length+1];
+		passargs[0]=String.valueOf(port);
+		for(int i=0; i<args.length; i++)
+			passargs[i+1]=args[i];
+		init(host,passargs);
 	}
-	public void init(String host, int port, String[] args) {
+	public void init(String host, String[] args) {
 		int strutsize=10;
 		int sepsize=5;
 		getContentPane().setLayout(new BorderLayout());
 		getContentPane().add(Box.createVerticalStrut(strutsize),BorderLayout.NORTH);
 		getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.WEST);
 		getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.EAST);
-		//always use RLE size for default - we'll assume it's full resolution
-		vision=null;
+		vision=new VisionPanel(host,args);
 		for(int i=0; i<args.length; i++) {
-			if(args[i].toUpperCase().compareTo("RLE")==0) {
+			if(args[i].toUpperCase().compareTo("RLE")==0 || args[i]==String.valueOf(VisionListener.defRLEPort)) {
 				setTitle("TekkotsuMon: Vision RLE");
-				vision=new VisionPanel(new VisionListener(host,port));
 				isRLE=true;
 				isRaw=false;
-				break;
-			} else if(args[i].toUpperCase().compareTo("RAW")==0) {
+			} else if(args[i].toUpperCase().compareTo("RAW")==0 || args[i]==String.valueOf(VisionListener.defRawPort)) {
 				setTitle("TekkotsuMon: Vision Raw");
-				vision=new VisionPanel(new VisionListener(host,port));
 				isRaw=true;
 				isRLE=false;
-				break;
-			} else
-				System.err.println("VisionGUI: Unrecognized argument: "+args[i]);
-		}
-		if(vision==null) {
-			vision=new VisionPanel(new VisionListener(host,port));
-			if(port==VisionListener.defRLEPort) {
-				setTitle("TekkotsuMon: Vision RLE");
-				isRLE=true;
-				isRaw=false;
-			} else {
-				setTitle("TekkotsuMon: Vision Raw");
-				isRLE=false;
-				isRaw=true;
 			}
 		}
 		vision.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
Index: tools/mon/org/tekkotsu/mon/VisionListener.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/VisionListener.java,v
retrieving revision 1.6
retrieving revision 1.9
diff -u -d -r1.6 -r1.9
--- tools/mon/org/tekkotsu/mon/VisionListener.java	20 Jan 2004 20:05:31 -0000	1.6
+++ tools/mon/org/tekkotsu/mon/VisionListener.java	28 Sep 2004 18:56:12 -0000	1.9
@@ -4,11 +4,8 @@
 import java.util.Vector;
 import java.util.Date;
 
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.net.Socket;
-import javax.swing.JFrame;
-import java.awt.Image;
+import java.io.*;
+import java.net.*;
 import java.awt.image.BufferedImage;
 import java.awt.image.Raster;
 import java.awt.image.IndexColorModel;
@@ -18,64 +15,7 @@
 import javax.imageio.stream.ImageInputStream;
 import javax.imageio.stream.MemoryCacheImageInputStream;
 
-public class VisionListener extends TCPListener {
-	boolean updatedFlag;
-	Date timestamp;
-	long frameNum=0;
-	final static int DEFAULT_WIDTH=176;
-	final static int DEFAULT_HEIGHT=144;
-
-	Vector listeners = new Vector();
-	void addListener(VisionUpdatedListener l) { listeners.add(l); }
-	void removeListener(VisionUpdatedListener l) { listeners.remove(l); }
-	void fireVisionUpdate() {
-		updatedFlag=true;
-		for(int i=0; i<listeners.size(); i++)
-			((VisionUpdatedListener)listeners.get(i)).visionUpdated(this);
-	}
-
-	public Date getTimeStamp() { return timestamp; }
-	public long getFrameNum() { return frameNum; }
-
-	public boolean hasData() {
-		return updatedFlag;
-	}
- 
-	public boolean isConnected() {
-		return _isConnected;
-	}
-
-	int channels=3;
-	int width=DEFAULT_WIDTH;
-	int height=DEFAULT_HEIGHT;
-	int pktSize=width*height*channels;
-	int oldformat=PACKET_VISIONRAW_FULL;
-	int format;
-	int compression;
-	int chan_id;
-
-	byte[] _data=new byte[pktSize];
-	byte[] _outd=new byte[pktSize];
-	byte[] _tmp=new byte[pktSize*2];
-	byte[] _jpeg=new byte[pktSize*2];
-	byte[] _newjpeg=new byte[pktSize*2];
-	boolean isJPEG=false;
-	int jpegLen=0;
-	int newjpegLen=0;
-	boolean isIndex=false;
-	boolean badCompressWarn=false;
-	int[] _pixels=new int[width*height];
-	BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
-	int bytesRead;
-	boolean convertRGB=true;
-	static int defRawPort=10011;
-	static int defRLEPort=10012;
-	IndexColorModel cmodel;
-
-	static ImageReader jpegReader=(ImageReader)ImageIO.getImageReadersByFormatName("jpeg").next();
-
-	Object packetFormatChangeLock=new Object();
-
+public interface VisionListener {
 	public static final int ENCODE_COLOR=0;
 	public static final int ENCODE_SINGLE_CHANNEL=1;
 	public static final int COMPRESS_NONE=0;
@@ -87,543 +27,46 @@
 	public static final int CHAN_Y_DX=4;
 	public static final int CHAN_Y_DXDY=5;
 
-	public boolean hasRawJPEG() { return isJPEG; }
-	public byte[] getJPEG() { return _jpeg; }
-	public int getJPEGLen() { return jpegLen; }
-	
-	public String readLoadSaveString(InputStream in) throws java.io.IOException {
-		int creatorLen=readInt(in);
-		if(!_isConnected) return ""; 
-		String creator=new String(readBytes(in,creatorLen));
-		if(!_isConnected) return "";
-		if(readChar(in)!='\0')
-			System.err.println("Misread LoadSave string? "+creator);
-		return creator;
-	}
-
-	public boolean readChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
-		readBytes(_tmp,in,chanW*chanH);
-		if(!_isConnected) return false;
-		return upsampleData(c,chanW,chanH);
-	}
-	public boolean upsampleData(int c, int chanW, int chanH) {
-		if(chanW==width && chanH==height) {
-			//special case: straight copy if image and channel are same size
-			for(int y=0;y<height;y++) {
-				int datarowstart=y*width*channels+c;
-				int tmprowstart=y*chanW;
-				for(int x=0;x<width;x++)
-					_data[datarowstart+x*channels]=_tmp[tmprowstart+x];
-			}
-			return true;
-		}
-		//otherwise this channel is subsampled, need to blow it up
-		//we'll linearly interpolate between pixels
-		//METHOD A:
-		//hold edges, interpolate through middle:
-		//  if we have 2 samples, scaling up to 4
-		//   index: 0   1    2   3
-		// maps to: 0  1/3  2/3  1
-		/*
-		float xsc=(chanW-1)/(float)(width-1);
-		float ysc=(chanH-1)/(float)(height-1);
-		for(int y=0;y<height-1;y++) {
-			int datarowstart=y*width*channels+c;
-			float ty=y*ysc;
-			int ly=(int)ty; //lower pixel index
-			float fy=ty-ly; //upper pixel weight
-			int tmprowstart=ly*chanW;
-			for(int x=0;x<width-1;x++) {
-				float tx=x*xsc;
-				int lx=(int)tx; //lower pixel index
-				float fx=tx-lx; //upper pixel weight
-
-				float lv=((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx;
-				float uv=((int)_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
-				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
-			}
-			_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
-		}
-		int datarowstart=width*(height-1)*channels+c;
-		int tmprowstart=chanW*(chanH-1);
-		for(int x=0;x<width-1;x++) {
-			float tx=x*xsc;
-			int lx=(int)tx; //lower pixel index
-			float fx=tx-lx; //upper pixel weight
-			_data[datarowstart+x*channels]=(byte)(((int)_tmp[tmprowstart+lx]&0xFF)*(1-fx)+((int)_tmp[tmprowstart+lx+1]&0xFF)*fx);
-		}
-		_data[datarowstart+(width-1)*channels]=_tmp[tmprowstart+chanW-1];
-		*/
-		
-		//Unfortunately, pixels are simply interleaved, starting at the
-		//top right.  So, Method A will stretch things to the bottom-right
-		//a bit.  This method holds left edge and spacing, so it lines up
-		//better with what's being transmitted (but the bottom right edges
-		//wind up smeared)
-		//METHOD B:
-		//  if we have 2 samples, scaling up to 4
-		//   index: 0   1    2   3
-		// maps to: 0  1/2   1   1  <-- this last one would be 3/2, so we have to replicate 1
-		float xsc=(chanW)/(float)(width);
-		float ysc=(chanH)/(float)(height);
-		int xgap=Math.round(1.0f/xsc);
-		int ygap=Math.round(1.0f/ysc);
-		for(int y=0;y<height-ygap;y++) {
-			int datarowstart=y*width*channels+c;
-			float ty=y*ysc;
-			int ly=(int)ty; //lower pixel index
-			float fy=ty-ly; //upper pixel weight
-			int tmprowstart=ly*chanW;
-			for(int x=0;x<width-xgap;x++) {
-				float tx=x*xsc;
-				int lx=(int)tx; //lower pixel index
-				float fx=tx-lx; //upper pixel weight
-
-				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
-				float uv=(_tmp[tmprowstart+lx+chanW]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1+chanW]&0xFF)*fx;
-				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
-			}
-			for(int x=width-xgap;x<width;x++) {
-				float lv=(_tmp[tmprowstart+chanW-1]&0xFF);
-				float uv=(_tmp[tmprowstart+chanW-1+chanW]&0xFF);
-				_data[datarowstart+x*channels]=(byte)(lv*(1-fy)+uv*fy);
-			}
-		}
-		for(int y=height-ygap;y<height;y++) {
-			int datarowstart=y*width*channels+c;
-			int tmprowstart=chanW*(chanH-1);
-			for(int x=0;x<width-xgap;x++) {
-				float tx=x*xsc;
-				int lx=(int)tx; //lower pixel index
-				float fx=tx-lx; //upper pixel weight
-
-				float lv=(_tmp[tmprowstart+lx]&0xFF)*(1-fx)+(_tmp[tmprowstart+lx+1]&0xFF)*fx;
-				_data[datarowstart+x*channels]=(byte)(lv);
-			}
-			for(int x=width-xgap;x<width;x++)
-				_data[datarowstart+x*channels]=_tmp[tmprowstart+chanW-1];
-		}
-		
-		return true;
-	}
-
-	public boolean readJPEGChannel(InputStream in, int c, int chanW, int chanH) throws java.io.IOException {
-		int len=readInt(in);
-		newjpegLen=len;
-		//System.out.println("len="+len);
-		if(!_isConnected) return false;
-		if(len>=_newjpeg.length) {
-			System.out.println("Not enough tmp room");
-			return false;
-		}
-		readBytes(_newjpeg,in,len);
-		if(!_isConnected) return false;
-		if(len>chanW*chanH*channels) {
-			if(!badCompressWarn) {
-				badCompressWarn=true;
-				System.out.println("Compressed image is larger than raw would be... :(");
-			}
-		} else {
-			if(badCompressWarn) {
-				badCompressWarn=false;
-				System.out.println("...ok, compressed image is smaller than raw now... :)");
-			}
-		}
-
-		try {
-			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
-			jpegReader.setInput(jpegStream); 
-			Raster decoded=jpegReader.readRaster(0,null);
-			int off=c;
-			for(int y=0; y<chanH; y++)
-				for(int x=0; x<chanW; x++) {
-					_data[off]=(byte)decoded.getSample(x,y,0);
-					off+=channels;
-				}
-		} catch(Exception ex) { ex.printStackTrace(); }
-		return true;
-	}
-
-	public boolean readJPEG(InputStream in, int chanW, int chanH) throws java.io.IOException {
-		int len=readInt(in);
-		newjpegLen=len;
-		//System.out.println("len="+len);
-		if(!_isConnected) return false;
-		if(len>=_newjpeg.length) {
-			System.out.println("Not enough tmp room");
-			return false;
-		}
-		readBytes(_newjpeg,in,len);
-		if(!_isConnected) return false;
-		if(len>chanW*chanH*channels) {
-			if(!badCompressWarn) {
-				badCompressWarn=true;
-				System.out.println("Compressed image is larger than raw would be... :(");
-			}
-		} else {
-			if(badCompressWarn) {
-				badCompressWarn=false;
-				System.out.println("...ok, compressed image is smaller than raw now... :)");
-			}
-		}
-
-		try {
-			ImageInputStream jpegStream=new MemoryCacheImageInputStream(new ByteArrayInputStream(_newjpeg));
-			jpegReader.setInput(jpegStream); 
-			Raster decoded=jpegReader.readRaster(0,null);
-			int off=0;
-			for(int y=0; y<chanH; y++)
-				for(int x=0; x<chanW; x++) {
-					_data[off++]=(byte)decoded.getSample(x,y,0);
-					_data[off++]=(byte)decoded.getSample(x,y,2);
-					_data[off++]=(byte)decoded.getSample(x,y,1);
-				}
-		} catch(Exception ex) { ex.printStackTrace(); }
-		return true;
-	}
+	static ImageReader jpegReader=(ImageReader)ImageIO.getImageReadersByFormatName("jpeg").next();
 
-	byte[] colormap = new byte[256*3];
-	public boolean readColorModel(InputStream in) throws java.io.IOException {
-		int len=readInt(in);
-		//System.out.println("len="+len);
-		if(!_isConnected) return false;
-		readBytes(colormap,in,len*3);
-		if(!_isConnected) return false;
-		//we'll do this stupid thing because we can't change an existing color model, and we don't want to make a new one for each frame
-		// (btw, java is stupid)
-		boolean makeNew=false;
-		if(cmodel==null || len!=cmodel.getMapSize()) {
-			makeNew=true;
-		} else {
-			int off=0;
-			for(int i=0; i<len; i++) {
-				if((byte)cmodel.getRed(i)!=colormap[off++] || (byte)cmodel.getGreen(i)!=colormap[off++] || (byte)cmodel.getBlue(i)!=colormap[off++]) {
-					makeNew=true;
-					break;
-				}
-			}
-		}
-		if(makeNew) {
-			//System.out.println("new color model");
-			cmodel=new IndexColorModel(7,len,colormap,0,false);
-		}
-		return true;
-	}
-	
-	public boolean readIndexedColor(InputStream in, int chanW, int chanH) throws java.io.IOException {
-		readBytes(_data,in,chanW*chanH);
-		if(!_isConnected) return false;
-		if(!readColorModel(in)) return false;
-		if(!_isConnected) return false;
-		isIndex=true;
-		return true;
-	}
+	final static int DEFAULT_WIDTH=176;
+	final static int DEFAULT_HEIGHT=144;
+	static int defRawPort=10011;
+	static int defRLEPort=10012;
 
-	public boolean readRLE(InputStream in, int chanW, int chanH) throws java.io.IOException {
-		int len=readInt(in);
-		if(!_isConnected) return false;
-		readBytes(_tmp,in,len*5);
-		if(!_isConnected) return false;
+	void addListener(VisionUpdatedListener l);
+	void removeListener(VisionUpdatedListener l);
+	void fireVisionUpdate();
+	public boolean isConnected();
 
-		int dpos=0;
-		int curx=0, cury=0;
-		for (; len>0 && cury<chanH;) {
-			byte color=_tmp[dpos++];
-			int x=((int)_tmp[dpos++]&0xFF);
-			x|=((int)_tmp[dpos++]&0xFF)<<8;
-			int rlen=((int)_tmp[dpos++]&0xFF);
-			rlen|=((int)_tmp[dpos++]&0xFF)<<8;
-			//System.out.println(color + " "+x + " "+rlen);
-			len--;
-			if (x < curx)
-				return false;
-			
-			for (; curx < x; curx++)
-				_data[cury*width+curx]=0;
-			
-			if (curx+rlen>width)
-				return false;
-			
-			for (; rlen>0; rlen--, curx++)
-				_data[cury*width+curx]=color;
-			if (curx==width) {
-				cury++;
-				curx=0;
-			}
-		}
-		if(!readColorModel(in)) return false;
-		if(!_isConnected) return false;
-		isIndex=true;
-		return true;
-	}
+	public Date getTimeStamp();
+	public long getFrameNum();
+	public IndexColorModel getColorModel();
 
-	public void connected(Socket socket) {
-		_isConnected=true;
-		fireVisionUpdate();
-		try {
-			InputStream in=socket.getInputStream();
-			_isConnected=true;
-			while (true) {
-				String type = readLoadSaveString(in);
-				if(!_isConnected) break; //System.out.println("Got type="+type);
-				if(!type.equals("TekkotsuImage")) {
-					System.err.println("Unrecognized type: "+type);
-					break;
-				}
-				format=readInt(in);
-				if(!_isConnected) break; //System.out.println("Got format="+format);
-				compression=readInt(in);
-				if(!_isConnected) break; //System.out.println("Got compression="+compression);
-				int newWidth=readInt(in);
-				if(!_isConnected) break; //System.out.println("Got newWidth="+newWidth);
-				int newHeight=readInt(in);
-				if(!_isConnected) break; //System.out.println("Got newHeight="+newHeight);
-				long timest=readInt(in);
-				if(timest<0)
-					timest+=(1L<<32);
-				if(!_isConnected) break; //System.out.println("Got timest="+timest);
-				frameNum=readInt(in);
-				if(frameNum<0)
-					frameNum+=(1L<<32);
-				if(!_isConnected) break; //System.out.println("Got frameNum="+frameNum);
-				
-				if (format!=oldformat || newWidth!=width || newHeight!=height) {
-					width=newWidth;
-					height=newHeight;
-					synchronized (packetFormatChangeLock) {
-						switch (format) {
-						case ENCODE_COLOR:
-							channels=3;
-							pktSize=width*height*channels;
-							break;
-						case ENCODE_SINGLE_CHANNEL:
-							channels=1;
-							pktSize=width*height*channels;
-							break;
-						default:
-							System.err.println("VisionRawListener: unknown packet type "+format);
-							throw new java.lang.NoSuchFieldException("fake exception");
-						}
-						_data=new byte[pktSize];
-						_outd=new byte[pktSize];
-						_tmp=new byte[pktSize];
-						_jpeg=new byte[pktSize*2<2000?2000:pktSize*2];
-						_newjpeg=new byte[pktSize*2<2000?2000:pktSize*2];
-						_pixels=new int[width*height];;
-						img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
-						oldformat=format;
-					}
-				}
-				
-				boolean failed=false;
-				for(int i=0; i<channels; i++) {
-					String creator = readLoadSaveString(in);
-					if(!_isConnected) break; //System.out.println("Got creator="+creator);
-					if(!creator.equals("FbkImage")) {
-						System.err.println("Unrecognized creator: "+creator);
-						failed=true; break;
-					} else {
-						int chanwidth=readInt(in);
-						if(!_isConnected) break; //System.out.println("Got chanwidth="+chanwidth);
-						int chanheight=readInt(in);
-						if(!_isConnected) break; //System.out.println("Got chanheight="+chanheight);
-						
-						if(chanwidth>width || chanheight>height) {
-							System.err.println("channel dimensions exceed image dimensions");
-							failed=true; break;
-						}
-						
-						int layer=readInt(in);
-						if(!_isConnected) break; //System.out.println("Got layer="+layer);
-						chan_id=readInt(in);
-						if(!_isConnected) break; //System.out.println("Got chan_id="+chan_id);
-				
-						String fmt=readLoadSaveString(in);
-						if(!_isConnected) break; //System.out.println("Got fmt="+fmt);
-						if(fmt.equals("blank")) {
-							isJPEG=false;
-							isIndex=false;
-							int useChan=(channels==1)?i:chan_id;
-							int off=useChan;
-							for(int y=0; y<height; y++)
-								for(int x=0; x<width; x++) {
-									_data[off]=(byte)(convertRGB?0x80:0);
-									off+=channels;
-								}
-						} else if(fmt.equals("RawImage")) {
-							isJPEG=false;
-							isIndex=false;
-							int useChan=(channels==1)?i:chan_id;
-							if(!readChannel(in,useChan,chanwidth,chanheight)) { failed=true; break; }
-						} else if(fmt.equals("JPEGGrayscale")) {
-							isIndex=false;
-							int useChan=(channels==1)?i:chan_id;
-							if(!readJPEGChannel(in,useChan,chanwidth,chanheight)) { failed=true; break; }
-							isJPEG=(channels==1);
-						} else if(fmt.equals("JPEGColor")) {
-							isIndex=false;
-							if(format==ENCODE_SINGLE_CHANNEL)
-								System.err.println("WTF? ");
-							if(!readJPEG(in,chanwidth,chanheight)) { failed=true; break; }
-							i=channels;
-							isJPEG=true;
-						} else if(fmt.equals("SegColorImage")) {
-							isJPEG=false;
-							isIndex=true;
-							if(!readIndexedColor(in,chanwidth,chanheight)) { failed=true; break; }
-						} else if(fmt.equals("RLEImage")) {
-							isJPEG=false;
-							isIndex=true;
-							if(!readRLE(in,chanwidth,chanheight)) { failed=true; break; }
-						} else {
-							isJPEG=false;
-							isIndex=false;
-							System.err.println("Unrecognized format: "+fmt);
-							failed=true; break;
-						}
-					}
-				}
-				if(failed || !_isConnected)
-					break;
-				
-				synchronized(_outd) {
-					byte[] temp=_data;
-					_data=_outd;
-					_outd=temp;
-					if(isJPEG) {
-						temp=_newjpeg;
-						_newjpeg=_jpeg;
-						_jpeg=temp;
-						int tempi=newjpegLen;
-						newjpegLen=jpegLen;
-						jpegLen=tempi;
-					}
-					timestamp=new Date(timest);
-				}
-				fireVisionUpdate();
-			}
-		} catch (Exception ex) { }
-		
-		try { socket.close(); } catch (Exception ex) { }
-		_isConnected=false;
-		fireVisionUpdate();
-	}
+	public boolean hasRawJPEG();
+	public byte[] getJPEG();
+	public int getJPEGLen();
 	
-	public byte[] getData() {
-//		frameTimer();
-		synchronized (_outd) {
-			updatedFlag=false;
-			return _outd;
-		}
-	}
-
-	public void setConvertRGB(boolean b) { 
-		if(b!=convertRGB) {
-			convertRGB=b;
-			updatedFlag=true;
-			for(int i=0; i<listeners.size(); i++)
-				((VisionUpdatedListener)listeners.get(i)).visionUpdated(this);
-		}
-	}
-	public boolean getConvertRGB() { return convertRGB; }
+	public byte[] getData();
+	public void setConvertRGB(boolean b);
+	public boolean getConvertRGB();
 
-	public int[] getYUVPixels() {
-		synchronized(packetFormatChangeLock) {
-			byte[] data=getData();
-			int offset=0;
-			for (int i=0; i<width*height; i++) {
-				int y=(int)data[offset++]&0xFF;
-				int u=(int)data[offset++]&0xFF;
-				int v=(int)data[offset++]&0xFF;
-				_pixels[i]=(255<<24) | (y<<16) | (u<<8) | v;
-			}
-		}
-		return _pixels;
-	}
+	public int[] getYUVPixels();
 
 	//This still uses RGB pixels just in case you want to display the
 	//intensity value into hues instead of black/white
-	public int[] getIntensityPixels() {
-		synchronized(packetFormatChangeLock) {
-			byte[] data=getData();
-			int offset=0;
-			if(!getConvertRGB()) {
-				for (int i=0; i<width*height; i++) {
-					int z=(int)data[offset++]&0xFF;
-					_pixels[i]=(255<<24) | (z<<16) | (z<<8) | z;
-				}
-			} else if(chan_id==CHAN_Y || chan_id==CHAN_Y_DY || chan_id==CHAN_Y_DX || chan_id==CHAN_Y_DXDY ) {
-				for (int i=0; i<width*height; i++) {
-					int z=(int)data[offset++]&0xFF;
-					_pixels[i]=pixelYUV2RGB(z,0x80,0x80);
-				}
-			} else if(chan_id==CHAN_U) {
-				for (int i=0; i<width*height; i++) {
-					int z=(int)data[offset++]&0xFF;
-					_pixels[i]=pixelYUV2RGB(0x80,z,0x80);
-				}
-			} else if(chan_id==CHAN_V) {
-				for (int i=0; i<width*height; i++) {
-					int z=(int)data[offset++]&0xFF;
-					_pixels[i]=pixelYUV2RGB(0x80,0x80,z);
-				}
-			}
-		}		
-		return _pixels;
-	}
-
-	public int[] getRGBPixels() {
-		synchronized(packetFormatChangeLock) {
-			byte[] data=getData();
-			int offset=0;
-			for (int i=0; i<width*height; i++) {
-				int y=(int)data[offset++]&0xFF;
-				int u=(int)data[offset++]&0xFF;
-				int v=(int)data[offset++]&0xFF;
-				_pixels[i]=pixelYUV2RGB(y, u, v);
-			}
-		}
-		return _pixels;
-	}
-
-	static final int pixelYUV2RGB(int y, int u, int v) {
-		u=u*2-255;
-		v=v*2-255;
-		int r=y+u;
-		int b=y+v;
-		u=u>>1;
-		v=(v>>2)-(v>>4);
-		int g=y-u-v;
-		if (r<0) r=0; if (g<0) g=0; if (b<0) b=0;
-		if (r>255) r=255; if (g>255) g=255; if (b>255) b=255;
-
-		return (255<<24) | (r<<16) | (g<<8) | b;
-	}
-
-	public BufferedImage getImage() {
-		if(isIndex) {
-			byte[] data=getData();
-			if(cmodel==null)
-				return img;
-			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
-				img=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_INDEXED,cmodel);
-			img.getRaster().setDataElements(0,0,width,height,data);
-		} else {
-			int[] pix;
-			if(img.getWidth()!=width || img.getHeight()!=height || img.getType()!=BufferedImage.TYPE_BYTE_INDEXED)
-				img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
-			if(format==ENCODE_COLOR)
-				pix=getConvertRGB()?getRGBPixels():getYUVPixels();
-			else
-				pix=getIntensityPixels();
-			img.setRGB(0,0,width,height,pix,0,width);
-		}
-		return img;
-	}
+	public int[] getIntensityPixels();
 
+	public int[] getRGBPixels();
 
+	public BufferedImage getImage();
 
-	public VisionListener() { super(); }
-	public VisionListener(int port) { super(port); }
-	public VisionListener(String host, int port) { super(host,port); }
+	public void startThread();
+	public void kill();
+	public void run();
+	public void runServer();
+	public void runConnect();
+	public void close();
+	public void setPort(int port);
+	public void setHostPort(String host, int port);
 }
Index: tools/mon/org/tekkotsu/mon/VisionPanel.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java,v
retrieving revision 1.4
retrieving revision 1.7
diff -u -d -r1.4 -r1.7
--- tools/mon/org/tekkotsu/mon/VisionPanel.java	5 Feb 2004 02:00:56 -0000	1.4
+++ tools/mon/org/tekkotsu/mon/VisionPanel.java	28 Sep 2004 22:12:38 -0000	1.7
@@ -17,10 +17,11 @@
 	float tgtAspect=-1;
 
 	public static void usage() {
-		System.out.println("Usage: java VisionPanel host [port|raw|rle]");
+		System.out.println("Usage: java VisionPanel host [port|raw|rle] [udp|tcp]");
 		System.out.println("       if port is not specified, it defaults to:");
 		System.out.println("       "+VisionListener.defRawPort+" for raw");
 		System.out.println("       "+VisionListener.defRLEPort+" for RLE.");
+		System.out.println("       if transport protocol is not specified, it defaults to UDP");
 		System.exit(2);
 	}
 
@@ -28,19 +29,15 @@
 		int port=-1;
 		if(s.length<2)
 			usage();
-		if(s[1].toUpperCase().compareTo("RLE")==0) {
-			port=VisionListener.defRLEPort;
-		} else if(s[1].toUpperCase().compareTo("RAW")==0) {
-			port=VisionListener.defRawPort;
-		} else {
-			port=Integer.parseInt(s[1]);
-		}
+		String[] args=new String[s.length-1];
+		for(int i=0; i<args.length; i++)
+			args[i]=s[i+1];
 
 		JFrame frame=new JFrame("TekkotsuMon: Vision");
 		frame.setBackground(Color.black);
 		//frame.getContentPane().setLayout(new FlowLayout());
 		frame.setSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2)); 
-		VisionPanel vision=new VisionPanel(new VisionListener(s[0],port));
+		VisionPanel vision=new VisionPanel(s[0],args);
 		frame.getContentPane().add(vision);
 		frame.addWindowListener(new WindowAdapter() {
 				public void windowClosing(WindowEvent e) { System.exit(0); } });
@@ -50,7 +47,57 @@
 	public void setConvertRGB(boolean b) { _listener.setConvertRGB(b); }
 	public boolean getConvertRGB() { return _listener.getConvertRGB(); }
 
-	protected VisionPanel(VisionListener listener) {
+	public VisionPanel(VisionListener listener) {
+		super();
+		init(listener);
+	}
+	
+	public VisionPanel(String host, String[] args) {
+		super();
+		boolean useUDP=true;
+		int port=0;
+		for(int i=0; i<args.length; i++) {
+			if(args[i].toUpperCase().compareTo("RLE")==0) {
+				port=VisionListener.defRLEPort;
+			} else if(args[i].toUpperCase().compareTo("RAW")==0) {
+				port=VisionListener.defRawPort;
+			} else if(args[i].toUpperCase().compareTo("UDP")==0) {
+				useUDP=true;
+			} else if(args[i].toUpperCase().compareTo("TCP")==0) {
+				useUDP=false;
+			} else if(args[i].length()>0) {
+				port=Integer.parseInt(args[i]);
+			}
+		}
+		if(port==0) {
+			System.err.println("VisionPanel port unspecified or 0 - check arguments");
+			System.exit(2);
+		}
+		
+		if(useUDP)
+			init(new UDPVisionListener(host,port));
+		else
+			init(new TCPVisionListener(host,port));
+	}	
+	
+	public VisionPanel(String host, int port, String[] args) {
+		super();
+		boolean useUDP=true;
+		for(int i=0; i<args.length; i++) {
+			if(args[i].toUpperCase().compareTo("UDP")==0) {
+				useUDP=true;
+			} else if(args[i].toUpperCase().compareTo("TCP")==0) {
+				useUDP=false;
+			}
+		}
+		System.out.println("Connecting to port "+port+" with udp=="+useUDP);
+		if(useUDP)
+			init(new UDPVisionListener(host,port));
+		else
+			init(new TCPVisionListener(host,port));
+	}
+	
+	public void init(VisionListener listener) {
 		_listener=listener;
 		_listener.addListener(this);
 		setBackground(Color.BLACK);
Index: tools/mon/org/tekkotsu/mon/VisualObjectInfo.java
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/VisualObjectInfo.java
diff -N tools/mon/org/tekkotsu/mon/VisualObjectInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/mon/org/tekkotsu/mon/VisualObjectInfo.java	22 Apr 2004 22:46:02 -0000	1.6
@@ -0,0 +1,46 @@
+package org.tekkotsu.mon;
+
+import java.awt.Graphics2D;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+// stores info for a VisualObject
+public class VisualObjectInfo {
+	static Icon icon = new ImageIcon("org/tekkotsu/mon/icons/unknown.png");
+//	int portnum; //! the port number this object will be serialized over
+	int id;
+	int parentId;
+	String name;
+
+	public VisualObjectInfo(int _id, int _parentId, String _name){
+//		portnum = _portnum;
+		id = _id;
+		parentId = _parentId;
+		name = _name;
+	}
+
+//	public int getPortNum() { return portnum; }
+	public int getId() { return id; }
+	public int getParentId() { return parentId; }
+	public String getName() { return name; }
+
+	// returns left-most coordinate of object
+	public float getLeft() { return 0; }
+	// returns right-most coordinate of object
+	public float getRight() { return 176; }
+	// returns top-most coordinate of object
+	public float getTop() { return 0; }
+	// returns bottom-most coordinate of object
+	public float getBottom() { return 144; }
+
+	public int getColor() { return 0; } // returning 0 by default
+
+	public String toString() {
+		return (name + "(id " + id + ", parentId " + parentId + ")");
+	}
+
+	public Icon getIcon() { return icon; }
+
+	public void renderTo(Graphics2D graphics) { }
+}
+
Index: tools/mon/org/tekkotsu/mon/WatchableMemoryListener.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemoryListener.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tools/mon/org/tekkotsu/mon/WatchableMemoryListener.java	2 Oct 2003 02:08:08 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/WatchableMemoryListener.java	16 Apr 2004 20:23:03 -0000	1.3
@@ -26,8 +26,9 @@
         
         WMvar wmvar=new WMvar(var_type, var_name, var_data, timestamp);
         synchronized(changesList) { changesList.add(wmvar); }
+				//System.out.println(var_type+" "+var_name);
       }
-    } catch (Exception ex) { }
+    } catch (Exception ex) { if((SocketException)ex==null) ex.printStackTrace(); }
 
     try { socket.close(); } catch (Exception ex) { }
     _isConnected=false;
Index: tools/mon/org/tekkotsu/mon/WorldStateJointsListener.java
===================================================================
RCS file: /afs/cs/project/skinnerbots/aibo/Tekkotsu/tools/mon/org/tekkotsu/mon/WorldStateJointsListener.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tools/mon/org/tekkotsu/mon/WorldStateJointsListener.java	2 Oct 2003 02:08:08 -0000	1.2
+++ tools/mon/org/tekkotsu/mon/WorldStateJointsListener.java	16 Apr 2004 05:51:29 -0000	1.3
@@ -16,13 +16,24 @@
       InputStream in=socket.getInputStream();
       while (true) {
         _data.timestamp=readInt(in);
-        for (int i=0; i<18; i++)
+				//System.out.println("time="+_data.timestamp);
+				int NumPIDJoints=readInt(in);
+				_data.positions=new float[NumPIDJoints];
+				_data.duties=new float[NumPIDJoints];
+				//System.out.println("pid="+NumPIDJoints);
+        for (int i=0; i<NumPIDJoints; i++)
           _data.positions[i]=readFloat(in);
-        for (int i=0; i<6; i++)
+				int NumSensors=readInt(in);
+				_data.sensors=new float[NumSensors];
+				//System.out.println("sensor="+NumSensors);
+        for (int i=0; i<NumSensors; i++)
           _data.sensors[i]=readFloat(in);
-        for (int i=0; i<8; i++)
+				int NumButtons=readInt(in);
+				_data.buttons=new float[NumButtons];
+				//System.out.println("button="+NumButtons);
+        for (int i=0; i<NumButtons; i++)
           _data.buttons[i]=readFloat(in);
-        for (int i=0; i<18; i++)
+        for (int i=0; i<NumPIDJoints; i++)
           _data.duties[i]=readFloat(in);
 
         synchronized(_outd) {
Index: tools/mon/org/tekkotsu/mon/icons/agent.png
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/icons/agent.png
diff -N tools/mon/org/tekkotsu/mon/icons/agent.png
Binary files /dev/null and /tmp/cvsntxe2u differ
Index: tools/mon/org/tekkotsu/mon/icons/ellipse.png
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/icons/ellipse.png
diff -N tools/mon/org/tekkotsu/mon/icons/ellipse.png
Binary files /dev/null and /tmp/cvsCzjpqr differ
Index: tools/mon/org/tekkotsu/mon/icons/line.png
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/icons/line.png
diff -N tools/mon/org/tekkotsu/mon/icons/line.png
Binary files /dev/null and /tmp/cvs7NJJOn differ
Index: tools/mon/org/tekkotsu/mon/icons/sketch.png
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/icons/sketch.png
diff -N tools/mon/org/tekkotsu/mon/icons/sketch.png
Binary files /dev/null and /tmp/cvs2Bledk differ
Index: tools/mon/org/tekkotsu/mon/icons/unknown.png
===================================================================
RCS file: tools/mon/org/tekkotsu/mon/icons/unknown.png
diff -N tools/mon/org/tekkotsu/mon/icons/unknown.png
Binary files /dev/null and /tmp/cvsvjsSBg differ
Index: tools/seg/TileTrain.java
===================================================================
RCS file: tools/seg/TileTrain.java
diff -N tools/seg/TileTrain.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/seg/TileTrain.java	28 Sep 2004 20:51:43 -0000	1.1
@@ -0,0 +1,577 @@
+/* 
+   TileTrain.java
+   Vision training tool to be used with the Tekkotsu framework.
+   Originally modified from ImageShow and VisionTrain
+   Requires ImageData
+   By Rob Salkin (salkin@cs.albany.edu) and Shawn Turner (st2750@albany.edu)
+   University at Albany - May 2004
+*/
+
+import java.awt.image.*;
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import java.awt.geom.*;
+
+public class TileTrain extends Canvas implements KeyListener, MouseListener, MouseMotionListener{
+    BufferedImage _image;
+    String[] names;         //tracking color names
+    byte[] tmap;            //threshold map
+    int[] RGBdata;
+    int[] YUVdata;
+    ImageData imageDataYUV; //for YUV data
+    ImageData imageDataRGB; //for RGB data
+    int count;             //color counter
+
+    int[] red;
+    int[] green;
+    int[] blue;
+
+    //tiling layout
+    //"prime" numbered layouts will run in a single row -- not very fun
+    
+    //dimensions                            W    H
+    private static int [][]  sizetable = { {0  , 0},   //0 images  
+					   {1  , 1},   //1
+					   {2  , 1},   //2
+					   {3  , 1},   //3
+					   {2  , 2},   //4, etc.
+					   {5  , 1},
+					   {3  , 2},
+					   {7  , 1},
+					   {4  , 2},
+					   {3  , 3},
+					   {5  , 2},
+					   {11 , 1},
+					   {4  , 3},   //12
+					   {13 , 1},
+					   {7  , 2},
+					   {5  , 3},
+					   {4  , 4},   //16
+					   {17 , 1},
+					   {6  , 3},
+					   {19 , 1},
+					   {5  , 4},
+					   {7  , 3},
+					   {11 , 2},
+					   {23 , 1},
+					   {6  , 4},
+					   {5  , 5}  };
+
+    private static final int MAX_DIM = 25;             // maximum tiling area. Should match table
+
+    //for storing YUV data
+    public static final int size_y=16, size_u=64, size_v=64;
+    public static final int size_total=size_y*size_u*size_v;
+
+
+    //for marquee tool
+    Area curArea;
+    Polygon curPoly;
+    int lastx, lasty;
+    
+    //for control
+    public static final int MODIFIER_NONE=0;
+    public static final int MODIFIER_SHIFT=1;
+    public static final int MODIFIER_CTRL=2;
+    public int curSelectModifier;
+    public int curSelectModified;
+
+
+    public static int WIDTH; // number of images wide
+    public static int HEIGHT; // number of images high
+    public static int TOTAL_IMGS; //total images
+
+    // per tile. Set in main, based on argc
+    public static int PIXEL_WIDTH;
+    public static int PIXEL_HEIGHT;
+    public static int TOTAL_PIXELS;
+
+    // maximum number of allowable color names
+    public static final int MAX_COLORS=8;
+
+    //all of these should be set on the command line
+    public static final int SMOOTH_FACTOR=2; //1 pixel used for (1 + (2*SMOOTH_FACTOR))^3 colors when same SMOOTH_FACTOR is used for Y,U,V
+    public static final int Y_SMOOTH_FACTOR=3;//SMOOTH_FACTOR; //Y should have greatest smoothing for lighting variation
+    public static final int U_SMOOTH_FACTOR=1;//SMOOTH_FACTOR; 
+    public static final int V_SMOOTH_FACTOR=1;//SMOOTH_FACTOR; 
+    
+    
+    public static void main(String args[]) {
+
+	System.out.println
+	    ("TileTrain is a vision training tool to be used with the Tekkotsu framework.\n"
+	     +"Originally modified from ImageShow and VisionTrain\n"
+	     +"Requires ImageData\n"
+	     +"By Rob Salkin (salkin@cs.albany.edu) and Shawn Turner (st2750@albany.edu)\n"
+	     +"University at Albany - May 2004\n");
+
+
+	if(args.length-1 <= 0 || args.length-1 > MAX_DIM){
+	    System.out.println("Number of images must be > 0 and <= "+MAX_DIM);
+	    usageAndExit(args.length-1);
+	}
+
+	//determine proper image size for tiling by model
+	if(args[0].equals("-is7")){
+	    System.out.println("Processing images for ERS7");
+	    PIXEL_WIDTH = 104;
+	    PIXEL_HEIGHT = 80;
+	}
+	else if(args[0].equals("-is2xx")){
+	    System.out.println("Processing images for ERS2xx");
+	    PIXEL_WIDTH = 88;
+	    PIXEL_HEIGHT = 72;
+	}
+	else{
+	    usageAndExit(args.length);
+	}
+
+	
+
+	TOTAL_PIXELS = PIXEL_WIDTH*PIXEL_HEIGHT;           //pixels per tile
+	
+	//set tile dimensions
+	WIDTH = sizetable[args.length-1][0];
+	HEIGHT = sizetable[args.length-1][1];
+	TOTAL_IMGS = WIDTH*HEIGHT;
+    
+	String files[]=new String[args.length-1];
+	for(int i=0; i<args.length-1; i++){
+	    files[i]=args[i+1];
+	}
+	
+	TileTrain tileTrain=new TileTrain(files);
+
+	JFrame fraDisplay = new JFrame();
+	fraDisplay.getContentPane().add(tileTrain);
+
+	//ALWAYS PACK! OTHERWISE ARRAY OFFSET PROBLEMS HAPPEN!!!
+	//	fraDisplay.setSize(WIDTH*PIXEL_WIDTH,HEIGHT*PIXEL_HEIGHT);
+	fraDisplay.setResizable(false);
+	fraDisplay.pack();
+	fraDisplay.show();
+		
+	fraDisplay.addWindowListener(new WindowAdapter() {
+		public void windowClosing(WindowEvent e) { System.exit(0); } });
+
+    }
+    
+    
+    public static void usageAndExit(int imgs) {
+	System.out.println("usage: java TileTrain -is[7|2xx] raw_image (up to "+MAX_DIM+" raw images -- you gave me "+imgs+")");
+	System.exit(1);
+    }
+    
+    public int[] getRGBdata(){
+	return RGBdata;
+    }
+
+    public int[] getYUVdata(){
+	return YUVdata;
+    }
+
+    public TileTrain (String args[]) {
+	ImageData imageDataRGB=new ImageData();
+	ImageData imageDataYUV=new ImageData();
+
+	tmap=new byte[size_total];
+
+	red=new int[MAX_COLORS];
+	green=new int[MAX_COLORS];
+	blue=new int[MAX_COLORS];
+
+	ImageData tempRGB;
+	ImageData tempYUV;
+
+	int iaRGB[];
+	int iaYUV[];
+	RGBdata=new int[TOTAL_IMGS*TOTAL_PIXELS];
+	YUVdata=new int[TOTAL_IMGS*TOTAL_PIXELS];
+	count=0;
+	try{
+	    for(int k=0;k<TOTAL_IMGS;k++){
+		
+		tempRGB=new ImageData();
+		tempYUV=new ImageData();
+		System.out.println("Loading " + args[k] );
+		tempRGB.loadYUVFileAsRGB(args[k]);
+		tempYUV.loadYUVFileAsYUV(args[k]);
+		iaYUV=tempYUV.getPixels();
+		iaRGB=tempRGB.getPixels();
+		
+		for(int h=0;h<PIXEL_HEIGHT;h++){
+		    for(int w=0;w<PIXEL_WIDTH;w++){
+			RGBdata[(k/WIDTH)*(WIDTH*TOTAL_PIXELS) //tile row offset
+				+(k%WIDTH)*(PIXEL_WIDTH)       //tile col offset 
+				+h*WIDTH*PIXEL_WIDTH           //pixel row offset
+				+w]                            //pixel col offset
+			    =iaRGB[h*PIXEL_WIDTH+w]; //RGB data for display
+			
+			YUVdata[(k/WIDTH)*(WIDTH*TOTAL_PIXELS) //tile row offset
+				+(k%WIDTH)*(PIXEL_WIDTH)       //tile col offset 
+				+h*WIDTH*PIXEL_WIDTH           //pixel row offset
+				+w]                            //pixel col offset
+			    =iaYUV[h*PIXEL_WIDTH+w]; //YUV data for seg use
+		    }
+		}
+	    }	    
+	}
+	catch(Exception e){
+	    System.out.println(e.getClass() + " thrown. \nPlease verify that the arguments to TileTrain" + 
+			       " are consistent with the robot model and image filenames before trying again.\n\n");
+	    
+	    e.printStackTrace();
+	    System.exit(1);
+	}
+   
+	setBackground(Color.black);
+	setSize(PIXEL_WIDTH*WIDTH, PIXEL_HEIGHT*HEIGHT);
+	_image=new BufferedImage(PIXEL_WIDTH*WIDTH, PIXEL_HEIGHT*HEIGHT,
+				 BufferedImage.TYPE_INT_RGB);
+	
+	showImage(RGBdata, tmap, PIXEL_WIDTH*WIDTH, PIXEL_HEIGHT*HEIGHT);
+	
+	names=new String[MAX_COLORS];
+	curArea = new Area();
+	addKeyListener(this);
+	addMouseListener(this);
+	addMouseMotionListener(this);     
+	
+	showHelp();
+
+    }
+
+    void showImage(int[] data, byte[] tmap, int width, int height) {
+	_image.getRaster().setDataElements(0,0,width,height,data);
+	repaint();
+    }
+
+    public void paint(Graphics graphics) {
+	update(graphics);
+    }
+
+    public void keyPressed(KeyEvent e) {
+	
+	//modified to carry the shift/control selection features from them image to the canvas.
+	if (e.getKeyCode()==KeyEvent.VK_SHIFT) {
+	    curSelectModifier=MODIFIER_SHIFT;
+	} else if (e.getKeyCode()==KeyEvent.VK_CONTROL) {
+	    curSelectModifier=MODIFIER_CTRL;
+	}
+    }
+    
+    public static void showHelp(){
+	JOptionPane.showMessageDialog
+	    (null,"Start by selecting as much of a target color as possible to be segmented.\n"+
+	     "Press N (=Name) to store the current selection and enter a name for the selection.\n"+
+	     "Press S (=Save) to save the stored selections to .tm and .col files.\n"+
+	     "Press C (=Clear) to clear ALL current mapped colors\n"+
+	     "Press Q (=Quit) to quit this program\n" +
+	     "Tips:\n"+
+	     "\t-Press N after each selection -- don't forget to do so before pressing S.\n"+
+	     "\t-Hold SHIFT to select multiple regions or append to regions.\n"+
+	     "\t-Hold CTRL to deselect from regions.\n"+
+	     "\t-On the color chooser, select a representative color that will stand out compared to other colors.\n"+
+	     "\t-Click anywhere in the window to deselect all regions -- useful after pressing N.\n"+
+	     "\t-All .tm and .col files should have names <=8 characters.\n"+
+	     "Press H (=Help) for this message.\n", "TileTrain Help", JOptionPane.OK_OPTION);
+    }
+    
+    public void keyReleased(KeyEvent e) { 
+	if (e.getKeyCode()==KeyEvent.VK_SHIFT
+	    ||e.getKeyCode()==KeyEvent.VK_CONTROL) {
+	    curSelectModifier=MODIFIER_NONE;
+	}
+	else if (e.getKeyCode()==KeyEvent.VK_H){
+	    showHelp();
+	}
+	else if (e.getKeyCode()==KeyEvent.VK_N){
+	    //verify we have colors left to create
+	    if(checkcolors() == false)
+		return;
+
+	    String tname = null;//temporary string for color name
+	    do{
+		tname=JOptionPane.showInputDialog("Enter name for color "+(count+1));
+	    }while(tname!=null&&tname.trim().equals(""));
+	    if(tname!=null){
+		names[count] = tname;
+		
+		Color segcol = null;//segmentation will be seen as this color
+		do{
+		    segcol = JColorChooser.showDialog(null, "Segmented Color", Color.WHITE);
+		}while(segcol == null);
+		
+		red[count]=segcol.getRed();
+		green[count]=segcol.getGreen();
+		blue[count]=segcol.getBlue();
+		
+		count++;
+		doCalc(tmap, size_total);
+		
+		System.out.println(tname + " stored");
+		
+		//clear the area
+		curArea.reset();
+		repaint();
+		
+		checkcolors();
+	    }
+	    else{
+		JOptionPane.showMessageDialog(null, "The current selection was not stored!");
+	    }
+	}	
+	else if (e.getKeyCode()==KeyEvent.VK_S){
+
+	    JFileChooser chooser=new JFileChooser();
+	    
+	    chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
+	    chooser.setSelectedFile(new File("default.tm"));
+	    int returnval=chooser.showSaveDialog(this);
+	    if (returnval==JFileChooser.APPROVE_OPTION) {
+		//bug fix for save path
+		save(chooser.getCurrentDirectory() + "/" + chooser.getSelectedFile().getName());   
+	    }   
+	}
+	else if (e.getKeyCode()==KeyEvent.VK_Q){
+	    if( (JOptionPane.showConfirmDialog(null, "Are you Sure?\nAll unsaved work will be lost!", "Quit?", 
+					       JOptionPane.OK_CANCEL_OPTION)) == JOptionPane.OK_OPTION)
+		System.exit(0);
+	}
+	else if (e.getKeyCode()==KeyEvent.VK_C){
+	    if( (JOptionPane.showConfirmDialog(null, "Are you Sure?\nAll Colors Will be lost!", "Clear Colors?", JOptionPane.OK_CANCEL_OPTION)) 
+		== JOptionPane.OK_OPTION)
+		count = 0;
+	}
+    
+    }
+
+    public void keyTyped(KeyEvent e) {
+
+    }
+
+    public boolean checkcolors(){
+	//do we have any usuable colors left?
+
+	if(count >= MAX_COLORS){
+	    JOptionPane.showMessageDialog(null, "The maximum number of creatable colors ("+MAX_COLORS+
+					  ") has been filled\nPlease save your work, or hit \"C\" to clear ALL colors");
+	    return false;
+	}
+	return true;
+    }
+					  
+
+    public void doCalc(byte[] tmap, int size){
+
+	int size_total=size;
+
+	int i,x,y,yuv,y_val,u_val,v_val,index;
+
+	int rgb,r_val,g_val,b_val;
+
+
+	if(count<=1){
+	    for(i=0; i<size_total; i++){
+		tmap[i]=(byte)0;
+	    }
+	}
+
+	//scan the whole tiled image
+	for(y=0;y<HEIGHT*PIXEL_HEIGHT;y++){
+	    for(x=0;x<WIDTH*PIXEL_WIDTH;x++){
+		//if the pixel is in the area selected
+		if(curArea.contains(x,y)){	//could it be done without .contains?
+		    //get the corresponding YUV pixel
+		    yuv=YUVdata[y*WIDTH*PIXEL_WIDTH+x];
+
+		    y_val=(yuv>>16)&0xff;
+		    u_val=(yuv>>8)&0xff;
+		    v_val=yuv&0xff;
+		    y_val=y_val>>4;
+		    u_val=u_val>>2;
+		    v_val=v_val>>2;
+
+		    //save the selected pixel color, or set it to conflict if previously set
+		    int y1,u1,v1;
+		    for(y1=y_val-Y_SMOOTH_FACTOR;y1<=y_val+Y_SMOOTH_FACTOR;y1++){
+			for(u1=u_val-U_SMOOTH_FACTOR;u1<=u_val+U_SMOOTH_FACTOR;u1++){
+			    for(v1=v_val-V_SMOOTH_FACTOR;v1<=v_val+V_SMOOTH_FACTOR;v1++){
+				index=(y1*size_u+u1)*size_v+v1;
+				
+				if(index>=0&&index<=size_total-1){
+				    if(tmap[index]==(byte)0){
+					tmap[index]=(byte)count;
+				    }
+				    else if(tmap[index]!=(byte)count){
+					tmap[index]=(byte)9;
+				    }
+				}
+			    }
+			}
+		    }
+		}
+	    }
+	}
+
+    }
+
+    public void save(String filename){
+	int dotpos=filename.lastIndexOf('.');
+	if (dotpos>0) filename=filename.substring(0,dotpos);
+    
+	try {
+	    FileOutputStream file_tm_fos=new FileOutputStream(filename + ".tm");
+	    OutputStreamWriter file_tm_osw=new OutputStreamWriter(file_tm_fos);
+	    file_tm_osw.write("TMAP\nYUV8\n" +
+			      size_y + " " + size_u + " " + size_v + "\n");
+	    file_tm_osw.flush();
+	    file_tm_fos.write(tmap);
+	    file_tm_osw.close();
+	    System.out.println(filename + ".tm saved");
+	} catch (Exception ex) {
+	    System.out.println("Error saving to "+filename +".tm: " + ex);
+	}
+
+	try {
+	    FileWriter file_col_fw=new FileWriter(filename + ".col");
+
+	    //grey
+	    file_col_fw.write("0 (128 128 128) \"unclassified\" 8 1.00\n");
+
+	    //selected colors
+	    for(int colors=0;colors<count;colors++){
+		//are 8 and 0.75 the best values?
+		file_col_fw.write((1+colors)+" ("+red[colors]+" "+green[colors]+" "+blue[colors]+") \""+names[colors]+"\" 8 0.75\n");
+	    }
+
+	    //black
+	    file_col_fw.write("9 (0 0 0) \"conflict\" 8 0.75\n");
+
+	    file_col_fw.close();
+
+	    System.out.println(filename + ".col saved");
+	    
+	} catch (Exception ex) {
+	    System.out.println("Error saving to "+filename + ".col: " + ex);
+	}
+
+
+
+    }
+
+    //ported mouse functions from TrainCanvas 
+    public void mousePressed(MouseEvent e) {
+
+	if (curArea==null) return;
+      
+	if (e.getButton()!=MouseEvent.BUTTON1) return;
+      
+	curSelectModified=curSelectModifier;
+      
+	if (curSelectModified!=MODIFIER_SHIFT
+	    && curSelectModified!=MODIFIER_CTRL)
+	    curArea.reset();
+      
+	curPoly=new Polygon();
+      
+	//standard
+	lastx=e.getX();
+	lasty=e.getY();
+	curPoly.addPoint(e.getX(), e.getY());
+      
+    
+	repaint();
+
+
+    }
+
+    public void mouseDragged(MouseEvent e) {
+	if (curArea==null) return;
+	try{
+	    int x=e.getX();
+	    int y=e.getY();
+	    if ((Math.abs(x-lastx)+Math.abs(y-lasty))>2) {
+		curPoly.addPoint(e.getX(), e.getY());
+		lastx=x;
+		lasty=y;
+		repaint();
+	    }
+	
+	}
+	catch(Exception ex){
+	    System.out.println("TileTrain::mouseDragged handled exception");
+	    System.out.println("Probably due to the mouse accidently dragging off the preview window");
+	}
+	repaint();
+      
+    }
+
+    public void mouseReleased(MouseEvent e) {
+	if (curArea==null) return;
+	if (e.getButton()!=MouseEvent.BUTTON1) return;
+	try{
+	    curPoly.addPoint(e.getX(), e.getY());
+
+  
+	    if (curPoly.npoints>=3) {
+		if (curSelectModified==MODIFIER_CTRL) curArea.subtract(new Area(curPoly));
+		else curArea.add(new Area(curPoly));
+	    }
+	}
+	catch(Exception ex){
+	    System.out.println("TileTrain::mouseReleased handled exception");
+	    System.out.println("Probably due to the mouse accidently dragging off the preview window");
+	}
+
+	curPoly=null;
+	repaint();
+    }
+
+    //pointing happening here
+    public void mouseMoved(MouseEvent e){
+      
+	//      repaint();
+      
+    }
+
+    public void mouseClicked(MouseEvent e){
+	
+    }
+
+    public void mouseExited(MouseEvent e){
+
+    }
+
+    public void mouseEntered(MouseEvent e){}
+    
+    public void update(Graphics g) {
+	Graphics2D g2d=(Graphics2D) g;
+
+	Dimension sz=getSize();
+      
+	//draw image
+	if (_image!=null)
+	    g2d.drawImage(_image, 0, 0, sz.width, sz.height, null);
+    
+	//line color
+	g2d.setColor(Color.white);
+
+	//add shapes
+	if (curArea!=null)
+	    g2d.draw(curArea);
+
+	if (curPoly!=null)
+	    g2d.draw(curPoly);
+  
+	//I hate that thing...so it's off.
+	//draw "hint" square
+	//g2d.drawRect(lastx-2, lasty-2, 5, 5);
+
+    }
+
+}
Index: tools/test/kinematics/IP210Camera.txt
===================================================================
RCS file: tools/test/kinematics/IP210Camera.txt
diff -N tools/test/kinematics/IP210Camera.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210Camera.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,13 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+0	0	0	0
+6	0	0	0
+4	-30.396	24.359	80.239
+4	30.396	24.359	80.239
+4	-24.81	-6.761	86.874
+4	24.81	-6.761	86.874
+4	-44.544	-4.143	25.654
+4	44.544	-4.143	25.654
+4	0	-54.181	10.106
+4	0	-50.284	-8.393
Index: tools/test/kinematics/IP210LBk.txt
===================================================================
RCS file: tools/test/kinematics/IP210LBk.txt
diff -N tools/test/kinematics/IP210LBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210LBk.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,23 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-3.461	25.628	0
+4	22.264	-21.637	11.213
+4	22.264	-21.637	-10.393
+4	46.709	-5.975	11.213
+4	46.709	-5.975	-10.393
+4	31.079	5.262	11.213
+4	31.079	5.262	-10.393
+4	0.659	-17.961	11.213
+4	0.659	-17.961	-10.393
+4	9.658	3.472	11.213
+4	9.658	3.472	-10.393
+3	34.173	10.544	12.357
+3	34.173	-10.26	12.357
+3	30.39	10.217	-13.27
+3	30.39	-9.928	-13.27
+3	11.262	-10.257	14.729
+3	0	11.375	14.729
+3	11.262	-10.257	-14.729
+3	0	11.375	-14.729
Index: tools/test/kinematics/IP210LFr.txt
===================================================================
RCS file: tools/test/kinematics/IP210LFr.txt
diff -N tools/test/kinematics/IP210LFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210LFr.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,21 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	13.068	22.315	0
+4	32.041	8.21	11.213
+4	32.041	8.21	-10.393
+4	32.479	-18.491	11.213
+4	32.479	-18.491	-10.393
+4	8.379	3.9	11.213
+4	8.379	3.9	-10.393
+4	-0.978	-16.947	11.213
+4	-0.978	-16.947	-10.393
+3	30.39	10.544	13.27
+3	30.39	-10.26	13.27
+3	34.173	10.217	-12.357
+3	34.173	-9.928	-12.357
+3	11.262	-10.257	14.729
+3	0	11.375	14.729
+3	11.262	-10.257	-14.729
+3	0	11.375	-14.729
Index: tools/test/kinematics/IP210Mouth.txt
===================================================================
RCS file: tools/test/kinematics/IP210Mouth.txt
diff -N tools/test/kinematics/IP210Mouth.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210Mouth.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,7 @@
+5	0	0	0
+5	8.709	45.22	14.514
+5	8.709	45.22	-14.514
+5	-2.229	46.63	14.187
+5	-2.229	46.63	-14.187
+4	-14.187	23.577	70.806
+4	14.187	23.577	70.806
Index: tools/test/kinematics/IP210RBk.txt
===================================================================
RCS file: tools/test/kinematics/IP210RBk.txt
diff -N tools/test/kinematics/IP210RBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210RBk.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,23 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-3.461	25.628	0
+4	22.264	-21.637	-10.393
+4	22.264	-21.637	11.213
+4	46.709	-5.975	-10.393
+4	46.709	-5.975	11.213
+4	31.079	5.262	-10.393
+4	31.079	5.262	11.213
+4	0.659	-17.961	-10.393
+4	0.659	-17.961	11.213
+4	9.658	3.472	-10.393
+4	9.658	3.472	11.213
+3	34.173	-10.26	-12.357
+3	34.173	10.544	-12.357
+3	30.39	-9.928	13.27
+3	30.39	10.217	13.27
+3	0	11.375	-14.729
+3	11.262	-10.257	-14.729
+3	0	11.375	14.729
+3	11.262	-10.257	14.729
Index: tools/test/kinematics/IP210RFr.txt
===================================================================
RCS file: tools/test/kinematics/IP210RFr.txt
diff -N tools/test/kinematics/IP210RFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP210RFr.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,21 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	13.068	22.315	0
+4	32.041	8.21	-10.393
+4	32.041	8.21	11.213
+4	32.479	-18.491	-10.393
+4	32.479	-18.491	11.213
+4	8.379	3.9	-10.393
+4	8.379	3.9	11.213
+4	-0.978	-16.947	-10.393
+4	-0.978	-16.947	11.213
+3	30.39	-10.26	-13.27
+3	30.39	10.544	-13.27
+3	34.173	-9.928	12.357
+3	34.173	10.217	12.357
+3	0	11.375	-14.729
+3	11.262	-10.257	-14.729
+3	0	11.375	14.729
+3	11.262	-10.257	14.729
Index: tools/test/kinematics/IP220Camera.txt
===================================================================
RCS file: tools/test/kinematics/IP220Camera.txt
diff -N tools/test/kinematics/IP220Camera.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP220Camera.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,14 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+0	0	0	0
+6	0	0	0
+4	-20.075	17.745	71.039
+4	20.075	17.745	71.039
+4	-33.782	-22.574	71.039
+4	33.782	-22.574	71.039
+4	-52.213	-17.71	0
+4	52.213	-17.71	0
+4	28.558	-44.223	-1.279
+4	28.558	-82.504	-15.888
+4	0	-56.295	46.32
Index: tools/test/kinematics/IP220LBk.txt
===================================================================
RCS file: tools/test/kinematics/IP220LBk.txt
diff -N tools/test/kinematics/IP220LBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP220LBk.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,23 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-3.461	25.628	0
+4	16.534	-21.884	11.213
+4	16.534	-21.884	-10.393
+4	46.709	-5.975	11.213
+4	46.709	-5.975	-10.393
+4	31.079	5.262	11.213
+4	31.079	5.262	-10.393
+4	5.688	-16.035	11.213
+4	5.688	-16.035	-10.393
+4	9.658	3.472	11.213
+4	9.658	3.472	-10.393
+3	30.305	10.829	12.608
+3	30.305	-10.612	12.608
+3	26.074	11.271	-12.205
+3	26.074	-10.612	-12.205
+3	10.785	10.506	11.845
+3	10.785	-10.612	11.845
+3	10.785	10.506	-11.845
+3	10.785	-10.612	-11.845
Index: tools/test/kinematics/IP220LFr.txt
===================================================================
RCS file: tools/test/kinematics/IP220LFr.txt
diff -N tools/test/kinematics/IP220LFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP220LFr.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,21 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	13.068	22.315	0
+4	36.856	14.853	11.213
+4	36.856	14.853	-10.393
+4	32.479	-18.491	11.213
+4	32.479	-18.491	-10.393
+4	8.379	3.9	11.213
+4	8.379	3.9	-10.393
+4	-0.978	-16.947	11.213
+4	-0.978	-16.947	-10.393
+3	26.074	10.829	12.205
+3	26.074	-10.612	12.205
+3	30.305	11.271	-12.608
+3	30.305	-10.612	-12.608
+3	10.785	10.506	11.845
+3	10.785	-10.612	11.845
+3	10.785	10.506	-11.845
+3	10.785	-10.612	-11.845
Index: tools/test/kinematics/IP220RBk.txt
===================================================================
RCS file: tools/test/kinematics/IP220RBk.txt
diff -N tools/test/kinematics/IP220RBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP220RBk.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,23 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-3.461	25.628	0
+4	16.534	-21.884	-10.393
+4	16.534	-21.884	11.213
+4	46.709	-5.975	-10.393
+4	46.709	-5.975	11.213
+4	31.079	5.262	-10.393
+4	31.079	5.262	11.213
+4	5.688	-16.035	-10.393
+4	5.688	-16.035	11.213
+4	9.658	3.472	-10.393
+4	9.658	3.472	11.213
+3	30.305	-10.612	-12.608
+3	30.305	10.829	-12.608
+3	26.074	-10.612	12.205
+3	26.074	11.271	12.205
+3	10.785	-10.612	-11.845
+3	10.785	10.506	-11.845
+3	10.785	-10.612	11.845
+3	10.785	10.506	11.845
Index: tools/test/kinematics/IP220RFr.txt
===================================================================
RCS file: tools/test/kinematics/IP220RFr.txt
diff -N tools/test/kinematics/IP220RFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP220RFr.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,21 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	13.068	22.315	0
+4	36.856	14.853	-10.393
+4	36.856	14.853	11.213
+4	32.479	-18.491	-10.393
+4	32.479	-18.491	11.213
+4	8.379	3.9	-10.393
+4	8.379	3.9	11.213
+4	-0.978	-16.947	-10.393
+4	-0.978	-16.947	11.213
+3	26.074	-10.612	-12.205
+3	26.074	10.829	-12.205
+3	30.305	-10.612	12.608
+3	30.305	11.271	12.608
+3	10.785	-10.612	-11.845
+3	10.785	10.506	-11.845
+3	10.785	-10.612	11.845
+3	10.785	10.506	11.845
Index: tools/test/kinematics/IP7Camera.txt
===================================================================
RCS file: tools/test/kinematics/IP7Camera.txt
diff -N tools/test/kinematics/IP7Camera.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7Camera.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,12 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+0	0	0	0
+6	0	0	0
+4	71.234	-27.781	-48.99
+4	71.234	-27.781	48.99
+4	71.234	9.992	-34.53
+4	71.234	9.992	34.53
+4	-14.657	19.571	-61.668
+4	-14.657	19.571	61.668
+4	-10.121	54.115	0
Index: tools/test/kinematics/IP7LBk.txt
===================================================================
RCS file: tools/test/kinematics/IP7LBk.txt
diff -N tools/test/kinematics/IP7LBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7LBk.txt	18 Oct 2004 21:16:36 -0000	1.3
@@ -0,0 +1,25 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-4.112	17.796	0
+4	26.395	-21.709	15.743		
+4	26.395	-21.709	-9.718
+4	48.211	-5.348	15.743
+4	48.211	-5.348	-9.718
+4	45.602	5.249	15.743
+4	45.602	5.249	-9.718
+4	26.685	-7.267	17.788
+4	26.685	-7.267	-11.766
+4	1.803	-14.371	15.018
+4	1.803	-14.371	-8.992
+4	21.072	6.169	15.018
+4	21.072	6.169	-8.992
+3	30.738	9.321	11.02
+3	30.738	-3.233	11.02
+3	30.738	9.321	-11.02
+3	30.738	-3.233	-11.02
+3	0	6.61	11.02
+3	0	-3.233	11.02
+3	0	6.61	-11.02
+3	0	-3.233	-11.02
Index: tools/test/kinematics/IP7LFr.txt
===================================================================
RCS file: tools/test/kinematics/IP7LFr.txt
diff -N tools/test/kinematics/IP7LFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7LFr.txt	18 Oct 2004 21:16:36 -0000	1.3
@@ -0,0 +1,25 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	4.603	18.943	0
+4	38.015	13.616	-15.743
+4	38.015	13.616	9.718
+4	40.395	-9.984	-15.743
+4	40.395	-9.984	9.718
+4	26.016	-16.926	-15.743
+4	26.016	-16.926	9.718
+4	26.962	-6.869	-17.788
+4	26.962	-6.869	11.766
+4	18.777	9.452	-15.018
+4	18.777	9.452	8.992
+4	4.101	-12.860	-15.018
+4	4.101	-12.860	8.992
+3	30.738	9.321	11.02
+3	30.738	-3.233	11.02
+3	30.738	9.321	-11.02
+3	30.738	-3.233	-11.02
+3	0	6.61	11.02
+3	0	-3.233	11.02
+3	0	6.61	-11.02
+3	0	-3.233	-11.02
Index: tools/test/kinematics/IP7Mouth.txt
===================================================================
RCS file: tools/test/kinematics/IP7Mouth.txt
diff -N tools/test/kinematics/IP7Mouth.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7Mouth.txt	11 Oct 2004 19:44:52 -0000	1.2
@@ -0,0 +1,7 @@
+5	0	0	0
+5	53.667	16.127	-21.188
+5	53.667	16.127	21.188
+5	50.419	14.718	-14.973
+5	50.419	14.718	14.973
+4	104.465	-29.285	-14.973
+4	104.465	-29.285	14.973
Index: tools/test/kinematics/IP7RBk.txt
===================================================================
RCS file: tools/test/kinematics/IP7RBk.txt
diff -N tools/test/kinematics/IP7RBk.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7RBk.txt	18 Oct 2004 21:16:36 -0000	1.3
@@ -0,0 +1,25 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	-4.112	17.796	0
+4	26.395	-21.709	9.718
+4	26.395	-21.709	-15.743
+4	48.211	-5.348	9.718
+4	48.211	-5.348	-15.743
+4	45.602	5.249	9.718
+4	45.602	5.249	-15.743
+4	26.685	-7.267	11.766
+4	26.685	-7.267	-17.788
+4	1.803	-14.371	8.992
+4	1.803	-14.371	-15.018
+4	21.072	6.169	8.992
+4	21.072	6.169	-15.018
+3	30.738	-3.233	-11.02
+3	30.738	9.321	-11.02
+3	30.738	-3.233	11.02
+3	30.738	9.321	11.02
+3	0	-3.233	-11.02
+3	0	6.61	-11.02
+3	0	-3.233	11.02
+3	0	6.61	11.02
Index: tools/test/kinematics/IP7RFr.txt
===================================================================
RCS file: tools/test/kinematics/IP7RFr.txt
diff -N tools/test/kinematics/IP7RFr.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IP7RFr.txt	18 Oct 2004 21:16:36 -0000	1.3
@@ -0,0 +1,25 @@
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+5	4.603	18.943	0
+4	38.015	13.616	-9.718
+4	38.015	13.616	15.743
+4	40.395	-9.984	-9.718
+4	40.395	-9.984	15.743
+4	26.016	-16.926	-9.718
+4	26.016	-16.926	15.743
+4	26.962	-6.869	-11.766
+4	26.962	-6.869	17.788
+4	18.777	9.452	-8.992
+4	18.777	9.452	15.018
+4	4.101	-12.860	-8.992
+4	4.101	-12.860	15.018
+3	30.738	-3.233	-11.02
+3	30.738	9.321	-11.02
+3	30.738	-3.233	11.02
+3	30.738	9.321	11.02
+3	0	-3.233	-11.02
+3	0	6.61	-11.02
+3	0	-3.233	11.02
+3	0	6.61	11.02
Index: tools/test/kinematics/Makefile
===================================================================
RCS file: tools/test/kinematics/Makefile
diff -N tools/test/kinematics/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/Makefile	5 Oct 2004 21:06:57 -0000	1.9
@@ -0,0 +1,175 @@
+# Modified from Roboop Makefile for GNU g++
+
+TEKKOTSU_ROOT ?= ../..
+TEKKOTSU_TARGET_MODEL ?= TGT_ERS7
+ROBOOP_ROOT := $(TEKKOTSU_ROOT)/Motion/roboop
+NEWMAT_ROOT := $(TEKKOTSU_ROOT)/Shared/newmat
+
+CXX = g++
+CXXFLAGS = -I $(NEWMAT_ROOT) -I $(ROBOOP_ROOT) -I $(TEKKOTSU_ROOT) -Wall -D_REENTRANT -g \
+	-Wall -W -Wlarger-than-8192 -Wpointer-arith -Wcast-qual \
+	-D$(TEKKOTSU_TARGET_MODEL) \
+
+#  -O2 -frename-registers -fomit-frame-pointer -ffast-math -fno-common \
+
+#-Wno-long-double
+LIBS = -L./ -ltekkotsu -lroboop -lnewmat -lm
+AR = ar
+AR2= ranlib
+
+all: test_kinematics
+
+test_kinematics: test_kinematics.o libnewmat.a libroboop.a libtekkotsu.a
+	$(CXX) test_kinematics.o $(LIBS) -g -Wall -o $@
+
+Deprobooplib = \
+   roboop/gnugraph.o   roboop/comp_dq.o   roboop/comp_dqp.o   roboop/delta_t.o \
+   roboop/dynamics.o   roboop/homogen.o   roboop/kinemat.o    roboop/robot.o   \
+   roboop/sensitiv.o   roboop/utils.o     roboop/quaternion.o roboop/config.o  \
+   roboop/trajectory.o roboop/clik.o      roboop/controller.o roboop/invkine.o \
+   roboop/control_select.o roboop/dynamics_sim.o
+
+Depnewmatlib = \
+   newmat/bandmat.o    newmat/cholesky.o   newmat/evalue.o     newmat/fft.o\
+   newmat/hholder.o    newmat/jacobi.o     newmat/myexcept.o   newmat/newmat1.o\
+   newmat/newmat2.o    newmat/newmat3.o    newmat/newmat4.o    newmat/newmat5.o\
+   newmat/newmat6.o    newmat/newmat7.o    newmat/newmat8.o    newmat/newmat9.o\
+   newmat/newmatex.o   newmat/newmatnl.o   newmat/newmatrm.o   \
+   newmat/sort.o       newmat/submat.o     newmat/svd.o        newmat/newfft.o
+   
+Deptekkotsulib = \
+   tekkotsu/Motion/Kinematics.o   tekkotsu/Motion/PostureEngine.o  \
+   tekkotsu/Shared/Config.o       tekkotsu/Wireless/Socket.o       \
+   tekkotsu/Shared/WorldState.o   tekkotsu/Shared/get_time.o       \
+   tekkotsu/Shared/Profiler.o     tekkotsu/Events/EventBase.o      \
+   tekkotsu/Shared/LoadSave.o     tekkotsu/Shared/TimeET.o
+
+DEPENDS = $(Deptekkotsulib:.o=.d)
+
+test_kinematics.o: $(Deproboooplib) $(Depnewmatlib) $(Deptekkotsulib)
+
+roboop/%.o : $(ROBOOP_ROOT)/%.cpp $(Depnewmatlib)
+	@if [ ! -e $(dir $@) ] ; then mkdir -p $(dir $@) ; fi
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+newmat/%.o : $(NEWMAT_ROOT)/%.cpp
+	@if [ ! -e $(dir $@) ] ; then mkdir -p $(dir $@) ; fi
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+tekkotsu/%.o :
+	@if [ ! -e $(dir $@) ] ; then mkdir -p $(dir $@) ; fi
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+%.o : %.cpp
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+%.d :
+	@src=$(patsubst %.d,%.cc,$(patsubst tekkotsu/%,$(TEKKOTSU_ROOT)/%,$@)); \
+	echo "$@..." | sed 's@.*$(TGT_BD)/@Generating @'; \
+	if [ ! -e $(dir $@) ] ; then mkdir -p $(dir $@) ; fi ; \
+	$(CXX) $(CXXFLAGS) -MP -MG -MT "$@" -MT "$(@:.d=.o)" -MM "$$src" > $@
+
+ifeq ($(findstring clean,$(MAKECMDGOALS)),)
+-include $(DEPENDS)
+endif
+
+libroboop.a : $(Deprobooplib)
+	rm -f $@
+	$(AR) rc $@ $(Deprobooplib)
+	$(AR2) $@
+
+libnewmat.a: $(Depnewmatlib)
+	rm -f $@
+	$(AR) rc $@ $(Depnewmatlib)
+	$(AR2) $@
+
+libtekkotsu.a: $(Deptekkotsulib)
+	rm -f $@
+	$(AR) rc $@ $(Deptekkotsulib)
+	$(AR2) $@
+
+roboop/controller.o: $(ROBOOP_ROOT)/controller.cpp $(ROBOOP_ROOT)/controller.h
+
+roboop/control_select.o: $(ROBOOP_ROOT)/control_select.cpp $(ROBOOP_ROOT)/control_select.h
+
+roboop/dynamics_sim.o: $(ROBOOP_ROOT)/dynamics_sim.cpp $(ROBOOP_ROOT)/dynamics_sim.h
+
+roboop/trajectory.o: $(ROBOOP_ROOT)/trajectory.cpp $(ROBOOP_ROOT)/trajectory.h
+
+roboop/clik.o :  $(ROBOOP_ROOT)/clik.cpp $(ROBOOP_ROOT)/clik.h $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/robot.o :  $(ROBOOP_ROOT)/robot.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/config.o : $(ROBOOP_ROOT)/config.cpp $(ROBOOP_ROOT)/config.h
+
+roboop/quaternion.o : $(ROBOOP_ROOT)/quaternion.cpp $(ROBOOP_ROOT)/quaternion.h
+
+roboop/gnugraph.o :  $(ROBOOP_ROOT)/gnugraph.cpp $(ROBOOP_ROOT)/gnugraph.h $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/comp_dq.o :  $(ROBOOP_ROOT)/comp_dq.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/comp_dqp.o :  $(ROBOOP_ROOT)/comp_dqp.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/delta_t.o :  $(ROBOOP_ROOT)/delta_t.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/dynamics.o :  $(ROBOOP_ROOT)/dynamics.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/homogen.o :  $(ROBOOP_ROOT)/homogen.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/invkine.o :  $(ROBOOP_ROOT)/invkine.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/kinemat.o :  $(ROBOOP_ROOT)/kinemat.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/sensitiv.o :  $(ROBOOP_ROOT)/sensitiv.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+roboop/utils.o :  $(ROBOOP_ROOT)/utils.cpp $(ROBOOP_ROOT)/utils.h $(ROBOOP_ROOT)/robot.h
+
+newmat/bandmat.o :  $(NEWMAT_ROOT)/bandmat.cpp
+
+newmat/cholesky.o :  $(NEWMAT_ROOT)/cholesky.cpp
+
+newmat/evalue.o :  $(NEWMAT_ROOT)/evalue.cpp
+
+newmat/fft.o :  $(NEWMAT_ROOT)/fft.cpp
+
+newmat/newfft.o :  $(NEWMAT_ROOT)/newfft.cpp
+
+newmat/hholder.o :  $(NEWMAT_ROOT)/hholder.cpp
+
+newmat/jacobi.o :  $(NEWMAT_ROOT)/jacobi.cpp
+
+newmat/myexcept.o :  $(NEWMAT_ROOT)/myexcept.cpp
+
+newmat/newmat1.o :  $(NEWMAT_ROOT)/newmat1.cpp
+
+newmat/newmat2.o :  $(NEWMAT_ROOT)/newmat2.cpp
+
+newmat/newmat3.o :  $(NEWMAT_ROOT)/newmat3.cpp
+
+newmat/newmat4.o :  $(NEWMAT_ROOT)/newmat4.cpp
+
+newmat/newmat5.o :  $(NEWMAT_ROOT)/newmat5.cpp
+
+newmat/newmat6.o :  $(NEWMAT_ROOT)/newmat6.cpp
+
+newmat/newmat7.o :  $(NEWMAT_ROOT)/newmat7.cpp
+
+newmat/newmat8.o :  $(NEWMAT_ROOT)/newmat8.cpp
+
+newmat/newmat9.o :  $(NEWMAT_ROOT)/newmat9.cpp
+
+newmat/newmatex.o :  $(NEWMAT_ROOT)/newmatex.cpp
+
+newmat/newmatnl.o :  $(NEWMAT_ROOT)/newmatnl.cpp
+
+newmat/newmatrm.o :  $(NEWMAT_ROOT)/newmatrm.cpp
+
+newmat/sort.o :  $(NEWMAT_ROOT)/sort.cpp
+
+newmat/submat.o :  $(NEWMAT_ROOT)/submat.cpp
+
+newmat/svd.o :  $(NEWMAT_ROOT)/svd.cpp
+
+clean:
+	rm -f *.o *.a
+	rm -rf newmat roboop tekkotsu
Index: tools/test/kinematics/cam2xx.txt
===================================================================
RCS file: tools/test/kinematics/cam2xx.txt
diff -N tools/test/kinematics/cam2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam2xx.txt	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1,4 @@
+0 50 90 75
+0 0 -90 0
+90 48 90 0
+180 66.6 0 0
Index: tools/test/kinematics/cam7.txt
===================================================================
RCS file: tools/test/kinematics/cam7.txt
diff -N tools/test/kinematics/cam7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam7.txt	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1,5 @@
+0 19.5 90 67.5
+0 0 -90 0
+0 80 90 0
+-90 0 -90 14.6
+-90 81.06 0 0
Index: tools/test/kinematics/cam_range210
===================================================================
RCS file: tools/test/kinematics/cam_range210
diff -N tools/test/kinematics/cam_range210
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam_range210	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -1.4311700e+00	   7.5049158e-01	
+  -1.5638150e+00	   1.5638150e+00	
+  -5.0614548e-01	   5.0614548e-01	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/cam_range220
===================================================================
RCS file: tools/test/kinematics/cam_range220
diff -N tools/test/kinematics/cam_range220
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam_range220	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -1.5446164e+00	   7.5049158e-01	
+  -1.5638150e+00	   1.5638150e+00	
+  -5.0614548e-01	   5.0614548e-01	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/cam_range7
===================================================================
RCS file: tools/test/kinematics/cam_range7
diff -N tools/test/kinematics/cam_range7
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam_range7	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,6 @@
+   0.0000000e+00	   0.0000000e+00	
+  -1.3089969e+00	   0.0000000e+00	
+  -1.5358897e+00	   1.5358897e+00	
+  -2.6179939e-01	   7.8539816e-01	
+   0.0000000e+00	   0.0000000e+00	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/cam_type2xx.txt
===================================================================
RCS file: tools/test/kinematics/cam_type2xx.txt
diff -N tools/test/kinematics/cam_type2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam_type2xx.txt	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1 @@
+3 0 0 0 1
Index: tools/test/kinematics/cam_type7.txt
===================================================================
RCS file: tools/test/kinematics/cam_type7.txt
diff -N tools/test/kinematics/cam_type7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/cam_type7.txt	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1 @@
+3 0 0 0 3 1
Index: tools/test/kinematics/closest_point_on_line.m
===================================================================
RCS file: tools/test/kinematics/closest_point_on_line.m
diff -N tools/test/kinematics/closest_point_on_line.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/closest_point_on_line.m	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1,18 @@
+function Pb=closest_point_on_line(p,vec,o)
+%closest point on line returns the point of intersection of vec and shortest line connecting p to vec
+%p is the point
+%vec is the vector
+%[optional] o is the position of origin which p and v are relative to (assumes [0 0 0] otherwise)
+if nargin==2,
+	c1=p.*vec;
+	c2=vec.*vec;
+	b=c1/c2;
+	Pb=b*vec;
+else
+	v=vec-o;
+	w=p-o;
+	c1=w.*v;
+	c2=v.*v;
+	b=c1/c2;
+	Pb=o+b*v;
+end
Index: tools/test/kinematics/dhtransform.m
===================================================================
RCS file: tools/test/kinematics/dhtransform.m
diff -N tools/test/kinematics/dhtransform.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/dhtransform.m	12 Sep 2004 06:07:46 -0000	1.1
@@ -0,0 +1,10 @@
+function T=dhtransform(dhrow)
+theta=dhrow(1);
+d=dhrow(2);
+alpha=dhrow(3);
+a=dhrow(4);
+T=[ [cos(theta) , -cos(alpha)*sin(theta) ,  sin(alpha)*sin(theta) , a*cos(theta) ];
+		[sin(theta) ,  cos(alpha)*cos(theta) , -cos(theta)*sin(alpha) , a*sin(theta) ];
+		[   0       ,       sin(alpha)       ,       cos(alpha)       ,      d       ];
+		[   0       ,           0            ,           0            ,      1       ] ];
+
Index: tools/test/kinematics/dhvisualize.m
===================================================================
RCS file: tools/test/kinematics/dhvisualize.m
diff -N tools/test/kinematics/dhvisualize.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/dhvisualize.m	27 Sep 2004 01:32:06 -0000	1.5
@@ -0,0 +1,33 @@
+function dhvisualize(origdh,type,q,range,axlen)
+dh=set_q(origdh,type,q);
+hold on;
+lp=zeros(3,size(dh,1)+1);
+for link=0:size(dh,1),
+	lp(:,link+1)=dehomog(kine(dh,link)*[0 0 0 1]');
+end
+plot3(lp(1,:),lp(2,:),lp(3,:),'g-');
+plot3(lp(1,:),lp(2,:),lp(3,:),'ko');
+limited=find((q==range(1:size(q,1),1) | q==range(1:size(q,1),2)) & range(1:size(q,1),1)~=range(1:size(q,1),2));
+for link=limited',
+	plot3(lp(1,link:link+1),lp(2,link:link+1),lp(3,link:link+1),'m--');
+end
+axis equal
+
+for link=0:size(dh,1),
+	axx=dehomog(kine(dh,link)*[[0 0 0 1];[axlen 0 0 1]]');
+	axy=dehomog(kine(dh,link)*[[0 0 0 1];[0 axlen 0 1]]');
+	axz=dehomog(kine(dh,link)*[[0 0 0 1];[0 0 axlen 1]]');
+	plot3(axx(1,:),axx(2,:),axx(3,:),'r-');
+	plot3(axy(1,:),axy(2,:),axy(3,:),'b-');
+	plot3(axz(1,:),axz(2,:),axz(3,:),'k-');
+end
+
+%hilight origin
+plot3(lp(1,1),lp(2,1),lp(3,1),'m*');
+
+hold off;
+
+function p=dehomog(ph)
+for c=1:size(ph,2)
+	p(:,c)=ph(1:3,c)/ph(4,c);
+end
Index: tools/test/kinematics/dist_point_to_vector.m
===================================================================
RCS file: tools/test/kinematics/dist_point_to_vector.m
diff -N tools/test/kinematics/dist_point_to_vector.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/dist_point_to_vector.m	14 Sep 2004 22:07:01 -0000	1.1
@@ -0,0 +1,19 @@
+function d=dist_point_to_vector(p,vec,o)
+%DIST_POINT_TO_VECTOR returns distance of shortest line connecting p to vec
+%p is the point
+%vec is the vector
+%[optional] o is the position of origin which p and v are relative to (assumes [0 0 0] otherwise)
+if nargin==2,
+	c1=dot(p,vec);
+	c2=dot(vec,vec);
+	b=c1/c2;
+	Pb=b*vec;
+else
+	v=vec-o;
+	w=p-o;
+	c1=dot(w,v);
+	c2=dot(v,v);
+	b=c1/c2;
+	Pb=o+b*v;
+end
+d=norm(p-Pb);
Index: tools/test/kinematics/front_leg_range7
===================================================================
RCS file: tools/test/kinematics/front_leg_range7
diff -N tools/test/kinematics/front_leg_range7
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/front_leg_range7	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -2.0071286e+00	   2.2689280e+00	
+  -1.7453293e-01	   1.5358897e+00	
+  -4.3633231e-01	   2.1293017e+00	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/hind_leg_range7
===================================================================
RCS file: tools/test/kinematics/hind_leg_range7
diff -N tools/test/kinematics/hind_leg_range7
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/hind_leg_range7	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -2.2689280e+00	   2.0071286e+00	
+  -1.7453293e-01	   1.5358897e+00	
+  -4.3633231e-01	   2.1293017e+00	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/inv_kin.m
===================================================================
RCS file: tools/test/kinematics/inv_kin.m
diff -N tools/test/kinematics/inv_kin.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/inv_kin.m	14 Oct 2004 21:59:29 -0000	1.16
@@ -0,0 +1,212 @@
+function q = inv_kin(dh,type,range,vec_proj,Pobj,endlink,Plink,second_invert,third_invert)
+%INV_KIN_ERS_LEG_POS computes position inverse kinematics for an AIBO leg
+%dh is the matrix representing the dh parameters
+%Pobj is the target position
+%endlink is the last link to move
+%Plink is point on that link (and represented relative to that link's frame)
+
+q=zeros(endlink,1);
+
+if endlink>=2,
+	if endlink>=3,
+		if endlink>=4,
+			q(4)=computeThirdERSLink(4,dh,type,range,q,Pobj,endlink,Plink,third_invert)
+		end
+		q(3)=computeSecondERSLink(3,dh,type,range,q,Pobj,endlink,Plink,second_invert)
+	end
+	q(2)=computeFirstERSLink(2,dh,type,range,q,Pobj,endlink,Plink)
+end
+
+%check if link 2 is maxed out
+limited=find((q==range(1:size(q,1),1) | q==range(1:size(q,1),2)) & range(1:size(q,1),1)~=range(1:size(q,1),2));
+if sum(limited==2)>0,
+	%redo links 3 and 4 since link 2 was limited
+	if endlink>=3,
+		if endlink>=4,
+			q(4)=computeSecondERSLink(4,dh,type,range,q,Pobj,endlink,Plink,second_invert)
+		end
+		q(3)=computeFirstERSLink(3,dh,type,range,q,Pobj,endlink,Plink)
+	end
+end
+
+%check again, maybe now link 3 is maxed out as well
+limited=find((q==range(1:size(q,1),1) | q==range(1:size(q,1),2)) & range(1:size(q,1),1)~=range(1:size(q,1),2));
+if sum(limited==3)>0 && endlink>=4,
+	%redo link 4 since link 3 was limited
+	q(4)=computeFirstERSLink(4,dh,type,range,q,Pobj,endlink,Plink)
+end
+
+if vec_proj,
+	%This method is an approximation, not entirely precise or fast as it could be
+	%Something to work on some more down the road! :)
+	poE=convertLink(dh,type,q,0,Pobj,endlink);
+	if poE(4)~=0,
+		poE=poE(1:3)/poE(4);
+	else
+		poE=poE(1:3);
+	end
+	plE=Plink(1:3);
+	if Plink(4)~=0,
+		plE=plE/Plink(4);
+	end
+	obj_comp_link=dot(plE,poE)/norm(plE)
+	if obj_comp_link<norm(plE),
+		obj_comp_link=obj_comp_link*.975; %.975 is a bit of fudge - accounts for joints moving Plink when adjusting
+	else
+		obj_comp_link=obj_comp_link/.975; %.975 is a bit of fudge - accounts for joints moving Plink when adjusting
+	end
+	obj_proj_link=[ obj_comp_link*plE/norm(plE) ; 1]
+	q=inv_kin(dh,type,range,false,Pobj,endlink,obj_proj_link,second_invert,third_invert);
+	ipvisualize(dh,type,q,endlink,Plink,'m:','ko');
+else
+	dhvisualize(dh,type,q,range,15);
+	hold on;
+	plot3(Pobj(1)/Pobj(4),Pobj(2)/Pobj(4),Pobj(3)/Pobj(4),'kx');
+	hold off;
+%	for f=1:endlink-1,
+%		if type(f)==0 || type(f)==1,
+%			p=convertLink(dh,type,q,endlink,Plink,f)
+%			ipvisualize(dh,type,q,f,p,'c:','ko');
+%		end
+%	end
+	ipvisualize(dh,type,q,endlink,Plink,'y-','ko');
+end
+
+function qd=computeThirdERSLink(curlink,dh,type,range,q,Pobj,endlink,Plink,invert)
+disp('computeThirdERSLink');
+ITOL=1e-6;
+%We'll compute the knee angle first, using the
+%  length of the thigh
+%  distance from knee to Plink
+%  distance from shoulder to Pobj
+%use law of cosines to find angle at knee of Pobj and Plink, and the difference is the amount to move
+pp=convertFrame(set_q(dh,type,q),curlink-1,[0 0 0 1]',curlink);
+pp(3)=0;
+previous_to_cur_len=homog_norm(pp) %shoulder_to_knee
+pl=convertLink(dh,type,q,endlink,Plink,curlink)
+if (abs(pl(1))<ITOL && abs(pl(2))<ITOL),
+	%Plink is along axis of rotation, nothing we do is going to move it, so don't bother
+	qd=q(curlink);
+	return;
+end
+if Plink(4)==0,
+	%We're dealing with an infinite ray
+	disp('out of reach (positive infinity)');
+	tl=atan2(pl(2),pl(1))
+	tp=atan2(pp(2),pp(1))
+	qd=normalize_angle(tp-tl)
+else
+	cur_to_plink_xyz_len=homog_norm(pl)
+	plz=pl(3);
+	pl(3)=0;
+	cur_to_plink_len=homog_norm(pl)
+	prev_to_pobj=convertFrame(set_q(dh,type,q),0,Pobj,curlink-1)
+	prev_to_pobj_xyz_len=homog_norm(prev_to_pobj);
+	prev_to_pobj(3)=0;
+	tgt_len=sqrt(prev_to_pobj_xyz_len^2-plz^2)
+	aor=(cur_to_plink_len^2+previous_to_cur_len^2-tgt_len^2)/(2*cur_to_plink_len*previous_to_cur_len)
+	tl=atan2(pl(2),pl(1))
+	tp=atan2(pp(2),pp(1))
+	al=normalize_angle(tp-tl)
+	%have to check if Pobj is within reach
+	if isinf(aor), %qd should be set to whatever it currently is, plink is along cur's z axis
+	elseif aor<-1, %Pobj is too far away - straighten out
+		disp('out of reach (negative)');
+		qd=pi+al;
+	elseif aor>1, %Pobj is too close to center of rotation - fold up
+		disp('out of reach (positive)');
+		qd=al;
+	else
+		ao=-acos(aor)
+		if invert,
+			ao=-ao;
+		end
+		qd=ao+al;
+		%qd=(pi-(pi-ao)*cur_to_plink_len/cur_to_plink_xyz_len)+al;
+	end
+	qd=normalize_angle(qd)
+end
+qd=limit_angle(qd,range(curlink,1),range(curlink,2))
+
+
+function qd=computeSecondERSLink(curlink,dh,type,range,q,Pobj,endlink,Plink,invert)
+disp('computeSecondERSLink');
+ITOL=1e-6;
+%Convert Pobj, Plink, z3 to be frame 'curlink' relative
+po=convertFrame(set_q(dh,type,q),0,Pobj,curlink)
+pl=convertLink(dh,type,q,endlink,Plink,curlink)
+pp=convertFrame(set_q(dh,type,q),curlink-1,[0 0 0 1]',curlink)
+zp=convertFrame(set_q(dh,type,q),curlink-1,[0 0 1 0]',curlink);
+zp(4)=1
+ao=pi/2-acos(dot(dehomog(zp),dehomog(po))/homog_norm(zp)/homog_norm(po))
+%alternative method for ao: (Doesn't quite work... but the idea is there...)
+%pop=convertFrame(set_q(dh,type,q),0,Pobj,curlink-1)
+%pox=norm(pop(1:2)/pop(4))-norm(pp(1:2)/pp(4))
+%poy=pop(3)/pop(4)+pp(3)/pp(4)
+%ao=atan2(poy,pox)
+if (abs(pl(1))<ITOL && abs(pl(2))<ITOL), %Plink is along axis of rotation, can't move it
+	qd=q(curlink);
+else
+	if pl(4)==0,
+		qd=computeFirstERSLink(curlink,dh,type,range,q,Pobj,endlink,Plink)
+	else
+		r=norm(pl(1:2)/pl(4)) %radius of link point around axis of rotation
+		tors=(r^2-(pl(3)*tan(ao))^2)/(r^2+(r*tan(ao))^2)
+		if tors<0,
+			disp('out of reach')
+			if xor(dot(zp(1:end-1),po(1:end-1))>0,dot(zp(1:end-1),pp(1:end-1))<0)
+				qd=-pi/2;
+			else
+				qd=pi/2;
+			end
+		else
+			to=acos(sqrt(tors))
+			if xor(dot(zp(1:end-1),po(1:end-1))>0,dot(zp(1:end-1),pp(1:end-1))<0)
+				to=-to;
+			end
+			if invert,
+				to=pi-to
+			end
+			tl=atan2(pl(2),pl(1))
+			qd=normalize_angle(to-tl);
+		end
+		qd=limit_angle(qd,range(curlink,1),range(curlink,2))
+	end
+end
+
+function qd=computeFirstERSLink(curlink,dh,type,range,q,Pobj,endlink,Plink)
+disp('computeFirstERSLink');
+ITOL=1e-6;
+%Convert Pobj and Plink to be frame 'curlink' relative
+po=convertFrame(set_q(dh,type,q),0,Pobj,curlink)
+pl=convertLink(dh,type,q,endlink,Plink,curlink)
+if (abs(pl(1))<ITOL && abs(pl(2))<ITOL), %Plink is along axis of rotation, can't move it
+	qd=q(curlink);
+else
+	to=atan2(po(2),po(1))
+	tl=atan2(pl(2),pl(1))
+	qd=normalize_angle(to-tl)
+	qd=limit_angle(qd,range(curlink,1),range(curlink,2));
+end
+
+function v=convertFrame(dh,cur,A,dest)
+v=inv(kine(dh,dest-1))*kine(dh,cur-1)*A;
+
+function v=convertLink(dh,type,q,cur,A,dest)
+if cur==0
+	v=rotz(-q(dest))*convertFrame(set_q(dh,type,q),cur,A,dest);
+else
+	v=rotz(-q(dest))*convertFrame(set_q(dh,type,q),cur,rotz(q(cur))*A,dest);
+end
+
+function w=dehomog(v)
+w=v(1:end-1)/v(end);
+
+function n=homog_norm(x)
+n=norm(dehomog(x));
+
+function r=normalize_angle(x)
+r=x-round(x/(pi*2))*pi*2;
+
+function T=rotz(t)
+T=dhtransform([t 0 0 0]);
Index: tools/test/kinematics/ipvisualize.m
===================================================================
RCS file: tools/test/kinematics/ipvisualize.m
diff -N tools/test/kinematics/ipvisualize.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/ipvisualize.m	5 Oct 2004 19:12:37 -0000	1.4
@@ -0,0 +1,22 @@
+function ipvisualize(dh,type,q,endlink,p,lstyle,estyle)
+%IPVISUALIZE draws a link from endlink to p
+%dh is the robot construction in denavit-hartenberg convention
+%type is the types of each joint (0 is rotational, 1 is prismatic, 2 is fixed (immobile))
+%q is the current joint positions
+%endlink is the link p is relative to
+%p is the point on endlink
+%lstyle is the plot style to use for line
+%estyle is the plot style to use for endpoint
+if(p(4)==0),
+	return
+end
+conf=set_q(dh,type,q);
+hold on
+fPlink=kine(conf,endlink-1)*rot_z(q(endlink))*p;
+elink=kine(conf,endlink-1)*[0 0 0 1]';
+plot3(fPlink(1)/fPlink(4),fPlink(2)/fPlink(4),fPlink(3)/fPlink(4),estyle);
+plot3([elink(1) ; fPlink(1)/fPlink(4)],[elink(2) ; fPlink(2)/fPlink(4)],[elink(3) ; fPlink(3)/fPlink(4)],lstyle);
+hold off
+
+function T=rot_z(t)
+T=dhtransform([t 0 0 0]);
Index: tools/test/kinematics/kine.m
===================================================================
RCS file: tools/test/kinematics/kine.m
diff -N tools/test/kinematics/kine.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/kine.m	27 Sep 2004 01:32:06 -0000	1.1
@@ -0,0 +1,7 @@
+function T=kine(dh,link)
+
+T=eye(4,4);
+
+for x=1:link,
+	T=T*dhtransform(dh(x,:));
+end
Index: tools/test/kinematics/kinverify.nb
===================================================================
RCS file: tools/test/kinematics/kinverify.nb
diff -N tools/test/kinematics/kinverify.nb
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/kinverify.nb	14 Sep 2004 22:07:01 -0000	1.2
@@ -0,0 +1,490 @@
+(************** Content-type: application/mathematica **************
+                     CreatedBy='Mathematica 5.0'
+
+                    Mathematica-Compatible Notebook
+
+This notebook can be used with any Mathematica-compatible
+application, such as Mathematica, MathReader or Publicon. The data
+for the notebook starts with the line containing stars above.
+
+To get the notebook into a Mathematica-compatible application, do
+one of the following:
+
+* Save the data starting with the line of stars above into a file
+  with a name ending in .nb, then open the file inside the
+  application;
+
+* Copy the data starting with the line of stars above to the
+  clipboard, then use the Paste menu command inside the application.
+
+Data for notebooks contains only printable 7-bit ASCII and can be
+sent directly in email or through ftp in text mode.  Newlines can be
+CR, LF or CRLF (Unix, Macintosh or MS-DOS style).
+
+NOTE: If you modify the data for this notebook not in a Mathematica-
+compatible application, you must delete the line below containing
+the word CacheID, otherwise Mathematica-compatible applications may
+try to use invalid cache data.
+
+For more information on notebooks and Mathematica-compatible 
+applications, contact Wolfram Research:
+  web: http://www.wolfram.com
+  email: info@wolfram.com
+  phone: +1-217-398-0700 (U.S.)
+
+Notebook reader applications are available free of charge from 
+Wolfram Research.
+*******************************************************************)
+
+(*CacheID: 232*)
+
+
+(*NotebookFileLineBreakTest
+NotebookFileLineBreakTest*)
+(*NotebookOptionsPosition[     14262,        396]*)
+(*NotebookOutlinePosition[     14891,        418]*)
+(*  CellTagsIndexPosition[     14847,        414]*)
+(*WindowFrame->Normal*)
+
+
+
+Notebook[{
+Cell[BoxData[{
+    RowBox[{
+      RowBox[{"DHMatrix4", "=", 
+        RowBox[{"Function", "[", 
+          RowBox[{\({theta, d, alpha, a}\), ",", 
+            TagBox[
+              RowBox[{"(", "\[NoBreak]", GridBox[{
+                    {\(Cos[
+                        theta]\), \(\(-Cos[alpha]\)\ Sin[theta]\), \(Sin[
+                          alpha]\ Sin[theta]\), \(a\ Cos[theta]\)},
+                    {\(Sin[
+                        theta]\), \(Cos[alpha]\ Cos[
+                          theta]\), \(\(-Cos[theta]\)\ Sin[alpha]\), \(a\ Sin[
+                          theta]\)},
+                    {"0", \(Sin[alpha]\), \(Cos[alpha]\), "d"},
+                    {"0", "0", "0", "1"}
+                    }], "\[NoBreak]", ")"}],
+              Function[ BoxForm`e$, 
+                MatrixForm[ BoxForm`e$]]]}], "]"}]}], 
+      ";"}], "\[IndentingNewLine]", 
+    RowBox[{\(DHMatrix = 
+          Function[x, 
+            DHMatrix4[x[\([1]\)], x[\([2]\)], x[\([3]\)], x[\([4]\)]]];\), 
+      "\[IndentingNewLine]"}], "\[IndentingNewLine]", \(TabularDHMatrix\  = \ 
+        Function[
+          x, \[IndentingNewLine]ans = {}; \[IndentingNewLine]For[i = 1, 
+            i <= Length[x], \(i++\), \[IndentingNewLine]\(ans = 
+                Append[ans, 
+                  DHMatrix[
+                    x[\([i]\)]]];\)\[IndentingNewLine]]; \
+\[IndentingNewLine]ans\[IndentingNewLine]];\), "\[IndentingNewLine]", \(FKin \
+= Function[{x, n}, \[IndentingNewLine]ans = 
+            IdentityMatrix[4]; \[IndentingNewLine]For[i = 1, 
+            i \[LessEqual] n, \(i++\), 
+            ans = Simplify[
+                ans . x[\([i]\)]\ ]\ ]; \[IndentingNewLine]FullSimplify[
+            ans]\[IndentingNewLine]];\)}], "Input"],
+
+Cell[BoxData[{
+    RowBox[{
+      RowBox[{"lf7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "0", \(90  \[Degree]\), "65"},
+              {\(\(-90\) \[Degree]\), \(-62.5\), \(\(-90\) \[Degree]\), "0"},
+              {"0", "9", \(90  \[Degree]\), "69.5"},
+              {\(\(-4.428\) \[Degree]\), \(-4.7\), \(0  \[Degree]\), 
+                "63.572"},
+              {"0", "0", \(0  \[Degree]\), "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"rf7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "0", \(90  \[Degree]\), "65"},
+              {\(\(-90\) \[Degree]\), "62.5", \(90  \[Degree]\), "0"},
+              {"0", \(-9\), \(\(-90\) \[Degree]\), "69.5"},
+              {\(\(-4.428\) \[Degree]\), "4.7", \(0  \[Degree]\), "63.572"},
+              {"0", "0", \(0  \[Degree]\), "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"lh7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "0", \(\(-90\) \[Degree]\), \(-65\)},
+              {\(90  \[Degree]\), "62.5", \(90  \[Degree]\), "0"},
+              {"0", \(-9\), \(\(-90\) \[Degree]\), "69.5"},
+              {\(\(-27.011\) \[Degree]\), "4.7", \(180  \[Degree]\), 
+                "64.125"},
+              {"0", "0", \(0  \[Degree]\), "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{
+        RowBox[{"rh7", "=", 
+          RowBox[{"(", GridBox[{
+                {"0", "0", \(\(-90\) \[Degree]\), \(-65\)},
+                {\(90  \[Degree]\), \(-62.5\), \(\(-90\) \[Degree]\), "0"},
+                {"0", "9", \(90  \[Degree]\), "69.5"},
+                {\(\(-27.011\) \[Degree]\), \(-4.7\), \(180  \[Degree]\), 
+                  "64.125"},
+                {"0", "0", \(0  \[Degree]\), "0"}
+                }], ")"}]}], ";"}], 
+      "\[IndentingNewLine]"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"mouth7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "19.5", \(90  \[Degree]\), "67.5"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {"0", "80", \(90  \[Degree]\), "0"},
+              {\(\(-23.62937773065682`\) \[Degree]\), "0", "0", "43.6606"},
+              {\(7.3301480372107015`  \[Degree]\), "0", \(\(-90\) \[Degree]\),
+                 "42.0076"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"cam7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "19.5", \(90  \[Degree]\), "67.5"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {"0", "80", \(90  \[Degree]\), "0"},
+              {\(\(-90\) \[Degree]\), "0", \(\(-90\) \[Degree]\), "14.6"},
+              {\(\(-90\) \[Degree]\), "81.06", "0", "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"nir7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "19.5", \(90  \[Degree]\), "67.5"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {"0", "80", \(90  \[Degree]\), "0"},
+              {"0.0249189", "2.79525", "0", "76.9239"},
+              {"1.50041", "0", "1.55997", "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"fir7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "19.5", \(90  \[Degree]\), "67.5"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {"0", "80", \(90  \[Degree]\), "0"},
+              {"0.0136814", \(-8.04682\), "0", "76.9072"},
+              {"1.52305", "0", "1.56055", "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"cir7", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "19.5", \(90  \[Degree]\), "67.5"},
+              {\(60  \[Degree]\), "0", \(90  \[Degree]\), "1"},
+              {"0", \(35.5 + 12\), "0", "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"cir7b", "=", 
+        RowBox[{"(", GridBox[{
+              {
+                "0", \(19.5 + 47.5*Sin[\(-30\) \[Degree]] + 
+                  1*Sin[60  \[Degree]]\), \(90  \[Degree]\), \(67.5 + 
+                  47.5*Cos[\(-30\) \[Degree]] + 1*Cos[60  \[Degree]]\)},
+              {\(60  \[Degree]\), "0", \(90  \[Degree]\), "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"mouth2xx", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "50", \(90  \[Degree]\), "75"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {\(90  \[Degree]\), "48", \(90  \[Degree]\), "0"},
+              {\(\(-90\) \[Degree]\), "19.9547", \(90  \[Degree]\), 
+                "21.1774"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"cam2xx", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "50", \(90  \[Degree]\), "75"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {\(90  \[Degree]\), "48", \(90  \[Degree]\), "0"},
+              {"180", "66.6", "0", "0"}
+              }], ")"}]}], ";"}], "\[IndentingNewLine]", 
+    RowBox[{
+      RowBox[{"ir2xx", "=", 
+        RowBox[{"(", GridBox[{
+              {"0", "50", \(90  \[Degree]\), "75"},
+              {"0", "0", \(\(-90\) \[Degree]\), "0"},
+              {\(90  \[Degree]\), "48", \(90  \[Degree]\), "0"},
+              {\(-2.02003\), "26.5", "0", "16.2027"},
+              {"1.26156", "0", \(-0.0215808\), "0"}
+              }], ")"}]}], ";"}]}], "Input"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(FKin[TabularDHMatrix[lh7], 5] // MatrixForm\)], "Input"],
+
+Cell[BoxData[
+    TagBox[
+      RowBox[{"(", "\[NoBreak]", GridBox[{
+            {"0.4541615523442866`", "0.8909193478493033`", 
+              "0.`", \(-44.87689045592262`\)},
+            {"0.`", "0.`", \(-1.`\), "67.2`"},
+            {\(-0.8909193478493033`\), "0.4541615523442866`", 
+              "0.`", \(-126.63020318083657`\)},
+            {"0.`", "0.`", "0.`", "1.`"}
+            }], "\[NoBreak]", ")"}],
+      Function[ BoxForm`e$, 
+        MatrixForm[ BoxForm`e$]]]], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+    \(FKin[TabularDHMatrix[lh7], 5] // MatrixForm\), "\[IndentingNewLine]", 
+    \(FKin[TabularDHMatrix[lf7], 5] // MatrixForm\), "\[IndentingNewLine]", 
+    \(\((Inverse[FKin[TabularDHMatrix[cir7], 1]] . 
+          FKin[TabularDHMatrix[cir7], 3])\) // MatrixForm\)}], "Input"],
+
+Cell[BoxData[
+    TagBox[
+      RowBox[{"(", "\[NoBreak]", GridBox[{
+            {"0.4541615523442866`", "0.8909193478493033`", 
+              "0.`", \(-44.87689045592262`\)},
+            {"0.`", "0.`", \(-1.`\), "67.2`"},
+            {\(-0.8909193478493033`\), "0.4541615523442866`", 
+              "0.`", \(-126.63020318083657`\)},
+            {"0.`", "0.`", "0.`", "1.`"}
+            }], "\[NoBreak]", ")"}],
+      Function[ BoxForm`e$, 
+        MatrixForm[ BoxForm`e$]]]], "Output"],
+
+Cell[BoxData[
+    TagBox[
+      RowBox[{"(", "\[NoBreak]", GridBox[{
+            {\(-0.07720627083999129`\), "0.9970151411804045`", "0.`", 
+              "69.09184295016007`"},
+            {"0.`", "0.`", \(-1.`\), "67.2`"},
+            {\(-0.9970151411804045`\), \(-0.07720627083999129`\), 
+              "0.`", \(-132.88224655512067`\)},
+            {"0.`", "0.`", "0.`", "1.`"}
+            }], "\[NoBreak]", ")"}],
+      Function[ BoxForm`e$, 
+        MatrixForm[ BoxForm`e$]]]], "Output"],
+
+Cell[BoxData[
+    TagBox[
+      RowBox[{"(", "\[NoBreak]", GridBox[{
+            {"0.5`", "0.`", "0.8660254037844386`", "41.63620667976083`"},
+            {"0.8660254037844386`", 
+              "0.`", \(-0.5`\), \(-22.883974596215563`\)},
+            {"0.`", "1.`", "0.`", "0.`"},
+            {"0.`", "0.`", "0.`", "1.`"}
+            }], "\[NoBreak]", ")"}],
+      Function[ BoxForm`e$, 
+        MatrixForm[ BoxForm`e$]]]], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+    \(\(dhm = TabularDHMatrix[nir7];\)\), "\[IndentingNewLine]", 
+    \(Inverse[FKin[dhm, 3]] . FKin[dhm, 5] . {0, 0, 1, 1} - 
+      Inverse[FKin[dhm, 3]] . 
+        FKin[dhm, 5] . {0, 0, 0, 1}\), "\[IndentingNewLine]", 
+    \(FKin[dhm, 5] // TraditionalForm\)}], "Input"],
+
+Cell[BoxData[
+    \({0.9989079910696432`, \(-0.04544909905165828`\), 0.010826115305011541`, 
+      0.`}\)], "Output"],
+
+Cell[BoxData[
+    FormBox[
+      RowBox[{"(", "\[NoBreak]", GridBox[{
+            {"0.04545176271146529`", \(-0.010814926889512378`\), 
+              "0.9989079910696456`", "144.40001822730866`"},
+            {
+              "0.`", \(-0.9999413958964808`\), \(-0.010826115305011513`\), \
+\(-2.79525`\)},
+            {"0.9989665346078519`", 
+              "0.000492066023930346`", \(-0.04544909905165821`\), 
+              "101.41666059843548`"},
+            {"0.`", "0.`", "0.`", "1.`"}
+            },
+          ColumnAlignments->{Decimal}], "\[NoBreak]", ")"}], 
+      TraditionalForm]], "Output"]
+}, Open  ]],
+
+Cell[BoxData[
+    \(\t\)], "Input"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(dif = 
+      FKin[dhm, 5] . {0, 0, 0, 1} - FKin[dhm, 4] . {0, 0, 0, 1}\)], "Input"],
+
+Cell[BoxData[
+    \({0.`, 0.`, 0.`, 0.`}\)], "Output"]
+}, Open  ]],
+
+Cell[BoxData[""], "Input"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(ArcTan[dif\[LeftDoubleBracket]1\[RightDoubleBracket], 
+          dif\[LeftDoubleBracket]3\[RightDoubleBracket]]/\[Pi]*180\)], "Input"],
+
+Cell[BoxData[
+    RowBox[{\(ArcTan::"indet"\), \(\(:\)\(\ \)\), "\<\"Indeterminate \
+expression \\!\\(ArcTan[\\(\\(0.`, 0.`\\)\\)]\\) encountered. \
+\\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\
+\\\", ButtonFrame->None, ButtonData:>\\\"General::indet\\\"]\\)\"\>"}]], \
+"Message"],
+
+Cell[BoxData[
+    \(Interval[{\(-180\), 180}]\)], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(ArcTan[40, \(-17.5\)]/\[Pi]*180\)], "Input"],
+
+Cell[BoxData[
+    \(\(-23.62937773065682`\)\)], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(ArcTan[19.9547, \(-21.1774\)]/\[Pi]*180\)], "Input"],
+
+Cell[BoxData[
+    \(\(-46.70268296020705`\)\)], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+    \(\(-90\) - 12.8916\), "\[IndentingNewLine]", 
+    \(\((\(-90\) - 12.8916)\)/180*\[Pi]\), "\[IndentingNewLine]", 
+    \(90 - 6.3025\), "\[IndentingNewLine]", 
+    \(\((90 - 6.3025)\) \[Degree]\)}], "Input"],
+
+Cell[BoxData[
+    \(\(-102.8916`\)\)], "Output"],
+
+Cell[BoxData[
+    \(\(-1.7957971926449976`\)\)], "Output"],
+
+Cell[BoxData[
+    \(83.6975`\)], "Output"],
+
+Cell[BoxData[
+    \(1.4607969506879541`\)], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(\(-23.62937773065682`\) \[Degree]\)], "Input"],
+
+Cell[BoxData[
+    \(\(-0.4124104415973874`\)\)], "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+    \(7.3301480372107015`  \[Degree]\)], "Input"],
+
+Cell[BoxData[
+    \(0.12793521790792656`\)], "Output"]
+}, Open  ]]
+},
+FrontEndVersion->"5.0 for X",
+ScreenRectangle->{{0, 1280}, {0, 1024}},
+WindowSize->{780, 709},
+WindowMargins->{{Automatic, -8}, {Automatic, 0}}
+]
+
+(*******************************************************************
+Cached data follows.  If you edit this Notebook file directly, not
+using Mathematica, you must remove the line containing CacheID at
+the top of  the file.  The cache data will then be recreated when
+you save this file from within Mathematica.
+*******************************************************************)
+
+(*CellTagsOutline
+CellTagsIndex->{}
+*)
+
+(*CellTagsIndex
+CellTagsIndex->{}
+*)
+
+(*NotebookFileOutline
+Notebook[{
+Cell[1754, 51, 1716, 36, 336, "Input"],
+Cell[3473, 89, 5431, 120, 1220, "Input"],
+
+Cell[CellGroupData[{
+Cell[8929, 213, 76, 1, 27, "Input"],
+Cell[9008, 216, 486, 11, 81, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[9531, 232, 292, 4, 75, "Input"],
+Cell[9826, 238, 486, 11, 81, "Output"],
+Cell[10315, 251, 491, 11, 81, "Output"],
+Cell[10809, 264, 433, 10, 81, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[11279, 279, 287, 5, 59, "Input"],
+Cell[11569, 286, 117, 2, 27, "Output"],
+Cell[11689, 290, 598, 14, 81, "Output"]
+}, Open  ]],
+Cell[12302, 307, 35, 1, 27, "Input"],
+
+Cell[CellGroupData[{
+Cell[12362, 312, 103, 2, 27, "Input"],
+Cell[12468, 316, 54, 1, 27, "Output"]
+}, Open  ]],
+Cell[12537, 320, 26, 0, 27, "Input"],
+
+Cell[CellGroupData[{
+Cell[12588, 324, 154, 2, 27, "Input"],
+Cell[12745, 328, 313, 5, 20, "Message"],
+Cell[13061, 335, 59, 1, 27, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[13157, 341, 64, 1, 27, "Input"],
+Cell[13224, 344, 57, 1, 27, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[13318, 350, 72, 1, 27, "Input"],
+Cell[13393, 353, 57, 1, 27, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[13487, 359, 225, 4, 75, "Input"],
+Cell[13715, 365, 48, 1, 27, "Output"],
+Cell[13766, 368, 58, 1, 27, "Output"],
+Cell[13827, 371, 42, 1, 27, "Output"],
+Cell[13872, 374, 53, 1, 27, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[13962, 380, 66, 1, 27, "Input"],
+Cell[14031, 383, 58, 1, 27, "Output"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+Cell[14126, 389, 63, 1, 27, "Input"],
+Cell[14192, 392, 54, 1, 27, "Output"]
+}, Open  ]]
+}
+]
+*)
+
+
+
+(*******************************************************************
+End of Mathematica Notebook file.
+*******************************************************************)
+
Index: tools/test/kinematics/leg_range2xx
===================================================================
RCS file: tools/test/kinematics/leg_range2xx
diff -N tools/test/kinematics/leg_range2xx
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/leg_range2xx	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -2.0420352e+00	   2.0420352e+00	
+  -1.9198622e-01	   1.5533430e+00	
+  -4.7123890e-01	   2.5656340e+00	
+   0.0000000e+00	   0.0000000e+00	
Index: tools/test/kinematics/leg_type.txt
===================================================================
RCS file: tools/test/kinematics/leg_type.txt
diff -N tools/test/kinematics/leg_type.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/leg_type.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1 @@
+3 0 0 0 3
Index: tools/test/kinematics/lf2xx.txt
===================================================================
RCS file: tools/test/kinematics/lf2xx.txt
diff -N tools/test/kinematics/lf2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/lf2xx.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,5 @@
+0 0 90 59.5
+-90 -59.2 -90 0
+0 12.8 90 64
+-4.428 -0.5 0 63.572
+0 0 0 0
Index: tools/test/kinematics/lf7.txt
===================================================================
RCS file: tools/test/kinematics/lf7.txt
diff -N tools/test/kinematics/lf7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/lf7.txt	19 Oct 2004 07:37:20 -0000	1.2
@@ -0,0 +1,5 @@
+0 0 90 65
+-90 -62.5 -90 0
+0 9 90 69.5
+-4.081 -4.7 0 70.1646
+0 0 0 0
Index: tools/test/kinematics/lh2xx.txt
===================================================================
RCS file: tools/test/kinematics/lh2xx.txt
diff -N tools/test/kinematics/lh2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/lh2xx.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,5 @@
+0 0 -90 -59.5
+90 59.2 90 0
+0 -12.8 -90 64
+-27.011 0.5 180 64.125
+0 0 0 0
Index: tools/test/kinematics/lh7.txt
===================================================================
RCS file: tools/test/kinematics/lh7.txt
diff -N tools/test/kinematics/lh7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/lh7.txt	19 Oct 2004 07:37:20 -0000	1.2
@@ -0,0 +1,5 @@
+0 0 -90 -65
+90 62.5 90 0
+0 -9 -90 69.5
+-15.290 4.7 180 70.1646
+0 0 0 0
Index: tools/test/kinematics/limit_angle.m
===================================================================
RCS file: tools/test/kinematics/limit_angle.m
diff -N tools/test/kinematics/limit_angle.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/limit_angle.m	27 Sep 2004 01:32:06 -0000	1.1
@@ -0,0 +1,16 @@
+function y=limit_angle(x,mn,mx)
+if x<mn || x>mx
+	mn_dist=abs(normalize_angle(mn-x));
+	mx_dist=abs(normalize_angle(x-mx));
+	if mn_dist<mx_dist
+		y=mn;
+	else
+		y=mx;
+	end
+else
+	y=x;
+end
+
+function r=normalize_angle(x)
+r=x-round(x/(pi*2))*pi*2;
+
Index: tools/test/kinematics/loadDH.m
===================================================================
RCS file: tools/test/kinematics/loadDH.m
diff -N tools/test/kinematics/loadDH.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/loadDH.m	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,7 @@
+function dh = loadDH(file)
+%LOADDH loads Denavit-Hartenberg parameters from a text file
+%The only thing this does over matlab's own 'load' is convert
+%angles from degrees to radians
+%Data columns should be theta, d, alpha, a
+dh=load(file);
+dh(:,[1 3])=dh(:,[1 3])/180*pi;
Index: tools/test/kinematics/matlab.mat
===================================================================
RCS file: tools/test/kinematics/matlab.mat
diff -N tools/test/kinematics/matlab.mat
Binary files /dev/null and /tmp/cvsel8bAX differ
Index: tools/test/kinematics/mouth2xx.txt
===================================================================
RCS file: tools/test/kinematics/mouth2xx.txt
diff -N tools/test/kinematics/mouth2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth2xx.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,4 @@
+0 50 90 75
+0 0 -90 0
+90 48 90 0
+-90 19.9547 90 21.1774
Index: tools/test/kinematics/mouth7.txt
===================================================================
RCS file: tools/test/kinematics/mouth7.txt
diff -N tools/test/kinematics/mouth7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth7.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,4 @@
+0 19.5 90 67.5
+0 0 -90 0
+0 80 90 0
+-23.62937773065682 0 0 43.6606
Index: tools/test/kinematics/mouth7b.txt
===================================================================
RCS file: tools/test/kinematics/mouth7b.txt
diff -N tools/test/kinematics/mouth7b.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth7b.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,5 @@
+0 19.5 90 67.5
+0 0 -90 0
+0 80 90 0
+-23.62937773065682 0 0 43.6606
+7.3301480372107015 0 -90 42.0076
Index: tools/test/kinematics/mouth_range210
===================================================================
RCS file: tools/test/kinematics/mouth_range210
diff -N tools/test/kinematics/mouth_range210
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth_range210	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -1.4311700e+00	   7.5049158e-01	
+  -1.5638150e+00	   1.5638150e+00	
+  -5.0614548e-01	   5.0614548e-01	
+  -8.2030475e-01	  -5.2359878e-02	
Index: tools/test/kinematics/mouth_range7
===================================================================
RCS file: tools/test/kinematics/mouth_range7
diff -N tools/test/kinematics/mouth_range7
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth_range7	20 Sep 2004 21:54:32 -0000	1.1
@@ -0,0 +1,5 @@
+   0.0000000e+00	   0.0000000e+00	
+  -1.3089969e+00	   0.0000000e+00	
+  -1.5358897e+00	   1.5358897e+00	
+  -2.6179939e-01	   7.8539816e-01	
+  -9.5993109e-01	  -5.2359878e-02	
Index: tools/test/kinematics/mouth_type.txt
===================================================================
RCS file: tools/test/kinematics/mouth_type.txt
diff -N tools/test/kinematics/mouth_type.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/mouth_type.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1 @@
+3 0 0 0 0
Index: tools/test/kinematics/rf2xx.txt
===================================================================
RCS file: tools/test/kinematics/rf2xx.txt
diff -N tools/test/kinematics/rf2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/rf2xx.txt	14 Sep 2004 22:07:02 -0000	1.1
@@ -0,0 +1,5 @@
+0 0 90 59.5
+-90 59.2 90 0
+0 -12.8 -90 64
+-4.428 0.5 0 63.572
+0 0 0 0
Index: tools/test/kinematics/rf7.txt
===================================================================
RCS file: tools/test/kinematics/rf7.txt
diff -N tools/test/kinematics/rf7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/rf7.txt	19 Oct 2004 07:37:21 -0000	1.2
@@ -0,0 +1,5 @@
+0 0 90 65
+-90 62.5 90 0
+0 -9 -90 69.5
+-4.081 4.7 0 70.1646
+0 0 0 0
Index: tools/test/kinematics/rh2xx.txt
===================================================================
RCS file: tools/test/kinematics/rh2xx.txt
diff -N tools/test/kinematics/rh2xx.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/rh2xx.txt	14 Sep 2004 22:07:03 -0000	1.1
@@ -0,0 +1,5 @@
+0 0 -90 -59.5
+90 -59.2 -90 0
+0 12.8 90 64
+-27.011 -0.5 180 64.125
+0 0 0 0
Index: tools/test/kinematics/rh7.txt
===================================================================
RCS file: tools/test/kinematics/rh7.txt
diff -N tools/test/kinematics/rh7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/rh7.txt	19 Oct 2004 07:37:21 -0000	1.2
@@ -0,0 +1,5 @@
+0 0 -90 -65
+90 -62.5 -90 0
+0 9 90 69.5
+-15.290 -4.7 180 70.1646
+0 0 0 0
Index: tools/test/kinematics/set_q.m
===================================================================
RCS file: tools/test/kinematics/set_q.m
diff -N tools/test/kinematics/set_q.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/set_q.m	20 Sep 2004 22:54:21 -0000	1.4
@@ -0,0 +1,8 @@
+function dh = set_q(origdh,type,q)
+len=min([size(origdh,1) size(q,1)]);
+rot_idxs=find(type(1:len)==0);
+prism_idxs=find(type(1:len)==1);
+
+dh=origdh;
+dh(rot_idxs,1)=dh(rot_idxs,1)+q(rot_idxs,1);
+dh(prism_idxs,2)=dh(prism_idxs,2)+q(prism_idxs,1);
\ No newline at end of file
Index: tools/test/kinematics/test2xx.m
===================================================================
RCS file: tools/test/kinematics/test2xx.m
diff -N tools/test/kinematics/test2xx.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/test2xx.m	24 Sep 2004 21:37:37 -0000	1.1
@@ -0,0 +1,44 @@
+load;
+clf;
+
+p=[100 90 -110 1]';
+iplstyle='c-';
+ipestyle='co';
+
+disp('LFr2xx');
+%lfr_q=zeros(size(lf2xx,1),1);
+%dhvisualize(lf2xx,leg_type,lfr_q,leg_range2xx,15);
+lfr_q=inv_kin(lf2xx,leg_type,leg_range2xx,false,p,5,[10 10 10 1]',0,0)
+%for x=1:size(IP2xxLFr,1)
+%	ipvisualize(lf2xx,leg_type,lfr_q,IP2xxLFr(x,1),[IP2xxLFr(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('RFr2xx');
+rfr_q=zeros(size(rf2xx,1),1);
+%dhvisualize(rf2xx,leg_type,rfr_q,leg_range2xx,15);
+rfr_q=inv_kin(rf2xx,leg_type,leg_range2xx,false,[p(1) -p(2) p(3) p(4)]',5,[10 10 -10 1]',0,0)
+%for x=1:size(IP2xxRFr,1)
+%	ipvisualize(rf2xx,leg_type,rfr_q,IP2xxRFr(x,1),[IP2xxRFr(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('LBk2xx');
+lbk_q=zeros(size(lh2xx,1),1);
+%dhvisualize(lh2xx,leg_type,lbk_q,leg_range2xx,15);
+lbk_q=inv_kin(lh2xx,leg_type,leg_range2xx,false,[-p(1) p(2) p(3) p(4)]',5,[10 10 10 1]',0,0)
+%for x=1:size(IP2xxLBk,1)
+%	ipvisualize(lh2xx,leg_type,lbk_q,IP2xxLBk(x,1),[IP2xxLBk(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('RBk2xx');
+rbk_q=zeros(size(rh2xx,1),1);
+%dhvisualize(rh2xx,leg_type,rbk_q,leg_range2xx,15);
+rbk_q=inv_kin(rh2xx,leg_type,leg_range2xx,false,[-p(1) -p(2) p(3) p(4)]',5,[10 10 -10 1]',0,0)
+%for x=1:size(IP2xxRBk,1)
+%	ipvisualize(rh2xx,leg_type,rbk_q,IP2xxRBk(x,1),[IP2xxRBk(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('Cam210');
+cam_q=inv_kin(cam2xx,cam_type2xx,cam_range210,true,[280 -50 100 1]',5,[30 -10 50 1]',0,1)
+%for x=1:size(IP2xxCamera,1)
+%	ipvisualize(cam2xx,cam_type2xx,cam_q,IP2xxCamera(x,1),[IP2xxCamera(x,2:4)'; 1],iplstyle,ipestyle)
+%end
Index: tools/test/kinematics/test7.m
===================================================================
RCS file: tools/test/kinematics/test7.m
diff -N tools/test/kinematics/test7.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/test7.m	14 Oct 2004 19:25:23 -0000	1.4
@@ -0,0 +1,55 @@
+load;
+clf;
+
+p=[100 90 -110 1]';
+iplstyle='c-';
+ipestyle='co';
+
+disp('LFr7');
+%lfr_q=zeros(size(lf7,1),1);
+%dhvisualize(lf7,leg_type,lfr_q,front_leg_range7,15);
+lfr_q=inv_kin(lf7,leg_type,front_leg_range7,false,p,5,[10 10 10 1]',0,0)
+%for x=1:size(IP7LFr,1)
+%	ipvisualize(lf7,leg_type,lfr_q,IP7LFr(x,1),[IP7LFr(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('RFr7');
+rfr_q=zeros(size(rf7,1),1);
+%dhvisualize(rf7,leg_type,rfr_q,front_leg_range7,15);
+rfr_q=inv_kin(rf7,leg_type,front_leg_range7,false,[p(1) -p(2) p(3) p(4)]',5,[10 10 -10 1]',0,0)
+%for x=1:size(IP7RFr,1)
+%	ipvisualize(rf7,leg_type,rfr_q,IP7RFr(x,1),[IP7RFr(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('LBk7');
+lbk_q=zeros(size(lh7,1),1);
+%dhvisualize(lh7,leg_type,lbk_q,front_leg_range7,15);
+lbk_q=inv_kin(lh7,leg_type,hind_leg_range7,false,[-p(1) p(2) p(3) p(4)]',5,[10 10 10 1]',0,0)
+%for x=1:size(IP7LBk,1)
+%	ipvisualize(lh7,leg_type,lbk_q,IP7LBk(x,1),[IP7LBk(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('RBk7');
+rbk_q=zeros(size(rh7,1),1);
+%dhvisualize(rh7,leg_type,rbk_q,front_leg_range7,15);
+rbk_q=inv_kin(rh7,leg_type,hind_leg_range7,false,[-p(1) -p(2) p(3) p(4)]',5,[10 10 -10 1]',0,0)
+%for x=1:size(IP7RBk,1)
+%	ipvisualize(rh7,leg_type,rbk_q,IP7RBk(x,1),[IP7RBk(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+disp('Cam7');
+cam_q=inv_kin(cam7,cam_type7,cam_range7,true,[300 -50 190 1]',6,[0 0 1 0]',0,1)
+%for x=1:size(IP7Camera,1)
+%	ipvisualize(cam7,cam_type7,cam_q,IP7Camera(x,1),[IP7Camera(x,2:4)'; 1],iplstyle,ipestyle)
+%end
+
+
+
+
+
+
+
+
+
+
+%p=[0 90 0 1]';  %some out of reach points aren't handled very well...
Index: tools/test/kinematics/test_kinematics.cc
===================================================================
RCS file: tools/test/kinematics/test_kinematics.cc
diff -N tools/test/kinematics/test_kinematics.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/test_kinematics.cc	5 Oct 2004 19:12:37 -0000	1.11
@@ -0,0 +1,103 @@
+#include <iostream>
+#include <stdlib.h>
+#include "Motion/Kinematics.h"
+#include "Shared/Config.h"
+#include "Motion/PostureEngine.h"
+
+namespace ROBOOP {
+void serrprintf(const char* msg, int x, int y, int z) {
+	printf(msg,x,y,z);
+}
+};
+
+using namespace std;
+using namespace NEWMAT;
+
+unsigned int simulator_time=0;
+
+int main(int /*argc*/, char** /*argv*/) {
+	//Read config file
+	config=new Config("../../../project/ms/config/tekkotsu.cfg");
+	config->setValue(Config::sec_motion,"kinematics","../../../project/ms/config/ers7.kin");
+	kine = new Kinematics();
+	
+	PostureEngine pose;
+	for(unsigned int i=0; i<NumOutputs; i++)
+		pose(i).weight=0;
+	for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; i++)
+		pose(i).weight=1;
+	
+	ColumnVector Pobj(4);
+	//Pobj(1)=100;
+	//Pobj(2)=90;
+	//Pobj(3)=-110;
+	Pobj(1)=100;
+	Pobj(2)=90;
+	Pobj(3)=-110;
+	Pobj(4)=1;
+	
+	ColumnVector Plink(4);
+	Plink(1)=10;
+	Plink(2)=10;
+	Plink(3)=10;
+	Plink(4)=1;
+	
+	/*for(unsigned int i=LFrLegOffset; i<LFrLegOffset+JointsPerLeg; i++)
+		cout << outputNames[i] << ' ' << pose(i).value << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+KneeOffset,LFrLegOffset+KneeOffset) << endl<<endl;
+	cout << pose.getTransformFrames(LFrLegOffset+KneeOffset,LFrLegOffset+ElevatorOffset) << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+ElevatorOffset,LFrLegOffset+KneeOffset) << endl<<endl;
+	cout << pose.getTransformFrames(LFrLegOffset+KneeOffset,LFrLegOffset+RotatorOffset) << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+RotatorOffset,LFrLegOffset+KneeOffset) << endl<<endl;
+	cout << pose.getTransformFrames(LFrLegOffset+KneeOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformFrames(BaseFrameOffset,LFrLegOffset+KneeOffset) << endl;
+	*/
+
+//	pose(LFrLegOffset+RotatorOffset)=.5;
+//	pose(LFrLegOffset+ElevatorOffset)=.5;
+//	pose(LFrLegOffset+KneeOffset)=.5;
+	bool converged;
+	converged=pose.solveLinkPosition(Pobj,PawFrameOffset+LFrLegOrder,Plink);
+	cout << "LFr Converged=="<<converged<<endl;
+	Pobj(2)=-Pobj(2);
+	Plink(3)=-Plink(3);
+	converged=pose.solveLinkPosition(Pobj,PawFrameOffset+RFrLegOrder,Plink);
+	cout << "RFr Converged=="<<converged<<endl;
+	Pobj(2)=-Pobj(2);
+	Plink(3)=-Plink(3);
+	Pobj(1)=-Pobj(1);
+	converged=pose.solveLinkPosition(Pobj,PawFrameOffset+LBkLegOrder,Plink);
+	cout << "LBk Converged=="<<converged<<endl;
+	Pobj(2)=-Pobj(2);
+	Plink(3)=-Plink(3);
+	converged=pose.solveLinkPosition(Pobj,PawFrameOffset+RBkLegOrder,Plink);
+	cout << "RBk Converged=="<<converged<<endl;
+	Pobj(2)=-Pobj(2);
+	Plink(3)=-Plink(3);
+	Pobj(1)=-Pobj(1);
+
+	Pobj(1)=300;
+	Pobj(2)=-50;
+	Pobj(3)=190;
+	Plink=0; Plink(3)=1;
+	converged=pose.solveLinkVector(Pobj,CameraFrameOffset,Plink);
+	cout << "Camera Converged=="<<converged<<endl;
+
+	for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; i++)
+		cout << outputNames[i] << ' ' << pose(i).value << endl;
+		
+/*	cout << pose.getTransformFrames(BaseFrameOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+RotatorOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+ElevatorOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformFrames(LFrLegOffset+KneeOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformFrames(PawFrameOffset+LFrLegOrder,BaseFrameOffset) << endl;
+	
+	cout << pose.getTransformLinks(BaseFrameOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformLinks(LFrLegOffset+RotatorOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformLinks(LFrLegOffset+ElevatorOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformLinks(LFrLegOffset+KneeOffset,BaseFrameOffset) << endl;
+	cout << pose.getTransformLinks(PawFrameOffset+LFrLegOrder,BaseFrameOffset) << endl; */
+	
+	return 0;
+}
+
Index: tools/test/kinematics/vector_from_point_to_vector.m
===================================================================
RCS file: tools/test/kinematics/vector_from_point_to_vector.m
diff -N tools/test/kinematics/vector_from_point_to_vector.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/vector_from_point_to_vector.m	14 Sep 2004 22:07:03 -0000	1.1
@@ -0,0 +1,16 @@
+function d=vector_from_point_to_vector(p,vec,o)
+%VECTOR_FROM_POINT_TO_VECTOR returns the shortest line connecting p to vec
+%p is the point
+%vec is the vector
+%[optional] o is the position of origin which p and v are relative to
+if nargin==2,
+	o=[0 0 0];
+end
+
+v=vec-o;
+w=p-o;
+c1=dot(w,v);
+c2=dot(v,v);
+b=c1/c2;
+Pb=o+b*v;
+d=norm(p-Pb);
Index: tools/test/kinematics/IPorig/210.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/210.txt
diff -N tools/test/kinematics/IPorig/210.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/210.txt	18 Oct 2004 23:14:13 -0000	1.4
@@ -0,0 +1,109 @@
+LFr:elvtr	LFr	2	0	0	0
+LFr:rotor	LFr	3	0	0	0
+LFr:knee~	LFr	4	0	0	0
+RFr:elvtr	RFr	2	0	0	0
+RFr:rotor	RFr	3	0	0	0
+RFr:knee~	RFr	4	0	0	0
+LBk:elvtr	LBk	2	0	0	0
+LBk:rotor	LBk	3	0	0	0
+LBk:knee~	LBk	4	0	0	0
+RBk:elvtr	RBk	2	0	0	0
+RBk:rotor	RBk	3	0	0	0
+RBk:knee~	RBk	4	0	0	0
+NECK:tilt	Camera	2	0	0	0
+NECK:pan~	Camera	3	0	0	0
+NECK:nod~	Camera	4	0	0	0
+MOUTH~~~~	Mouth	5	0	0	0
+Base	Camera	0	0	0	0
+LFrPaw	LFr	5	0	0	0
+RFrPaw	RFr	5	0	0	0
+LBkPaw	LBk	5	0	0	0
+RBkPaw	RBk	5	0	0	0
+Camera	Camera	6	0	0	0
+IR	IR	6	0	0	0
+LowerLeftLowerLip	Mouth	5	8.709	45.22	14.514
+LowerRightLowerLip	Mouth	5	8.709	45.22	-14.514
+UpperLeftLowerLip	Mouth	5	-2.229	46.63	14.187
+UpperRightLowerLip	Mouth	5	-2.229	46.63	-14.187
+LowerLeftUpperLip	Mouth	4	-14.187	23.577	70.806
+LowerRightUpperLip	Mouth	4	14.187	23.577	70.806
+LowerLeftSnout	Camera	4	-30.396	24.359	80.239
+LowerRightSnout	Camera	4	30.396	24.359	80.239
+UpperLeftSnout	Camera	4	-24.81	-6.761	86.874
+UpperRightSnout	Camera	4	24.81	-6.761	86.874
+LeftMicrophone	Camera	4	-44.544	-4.143	25.654
+RightMicrophone	Camera	4	44.544	-4.143	25.654
+FrontHeadButton	Camera	4	0	-54.181	10.106
+RearHeadButton	Camera	4	0	-50.284	-8.393
+ToeLFrPaw	LFr	5	13.068	22.315	0
+ToeRFrPaw	RFr	5	13.068	22.315	0
+ToeLBkPaw	LBk	5	-3.461	25.628	0
+ToeRBkPaw	RBk	5	-3.461	25.628	0
+LowerOuterFrontLFrShin	LFr	4	32.041	8.21	-11.213
+LowerInnerFrontRFrShin	RFr	4	32.041	8.21	-10.393
+LowerOuterFrontLBkShin	LBk	4	22.264	-21.637	11.213
+LowerInnerFrontRBkShin	RBk	4	22.264	-21.637	10.393
+LowerInnerFrontLFrShin	LFr	4	32.041	8.21	10.393
+LowerOuterFrontRFrShin	RFr	4	32.041	8.21	11.213
+LowerInnerFrontLBkShin	LBk	4	22.264	-21.637	-10.393
+LowerOuterFrontRBkShin	RBk	4	22.264	-21.637	-11.213
+LowerOuterBackLFrShin	LFr	4	32.479	-18.491	-11.213
+LowerInnerBackRFrShin	RFr	4	32.479	-18.491	-10.393
+LowerOuterBackLBkShin	LBk	4	46.709	-5.975	11.213
+LowerInnerBackRBkShin	RBk	4	46.709	-5.975	10.393
+LowerInnerBackLFrShin	LFr	4	32.479	-18.491	10.393
+LowerOuterBackRFrShin	RFr	4	32.479	-18.491	11.213
+LowerInnerBackLBkShin	LBk	4	46.709	-5.975	-10.393
+LowerOuterBackRBkShin	RBk	4	46.709	-5.975	-11.213
+MiddleOuterBackLBkShin	LBk	4	31.079	5.262	11.213
+MiddleInnerBackRBkShin	RBk	4	31.079	5.262	10.393
+MiddleInnerBackLBkShin	LBk	4	31.079	5.262	-10.393
+MiddleOuterBackRBkShin	RBk	4	31.079	5.262	-11.213
+UpperOuterFrontLFrShin	LFr	4	8.379	3.9	-11.213
+UpperInnerFrontRFrShin	RFr	4	8.379	3.9	-10.393
+UpperOuterFrontLBkShin	LBk	4	0.659	-17.961	11.213
+UpperInnerFrontRBkShin	RBk	4	0.659	-17.961	10.393
+UpperInnerFrontLFrShin	LFr	4	8.379	3.9	10.393
+UpperOuterFrontRFrShin	RFr	4	8.379	3.9	11.213
+UpperInnerFrontLBkShin	LBk	4	0.659	-17.961	-10.393
+UpperOuterFrontRBkShin	RBk	4	0.659	-17.961	-11.213
+UpperOuterBackLFrShin	LFr	4	-0.978	-16.947	-11.213
+UpperInnerBackRFrShin	RFr	4	-0.978	-16.947	-10.393
+UpperOuterBackLBkShin	LBk	4	9.658	3.472	11.213
+UpperInnerBackRBkShin	RBk	4	9.658	3.472	10.393
+UpperInnerBackLFrShin	LFr	4	-0.978	-16.947	10.393
+UpperOuterBackRFrShin	RFr	4	-0.978	-16.947	11.213
+UpperInnerBackLBkShin	LBk	4	9.658	3.472	-10.393
+UpperOuterBackRBkShin	RBk	4	9.658	3.472	-11.213
+LowerOuterFrontLFrThigh	LFr	3	30.39	10.544	13.27
+LowerInnerFrontRFrThigh	RFr	3	30.39	-10.26	-13.27
+LowerOuterFrontLBkThigh	LBk	3	34.173	10.544	12.357
+LowerInnerFrontRBkThigh	RBk	3	34.173	-10.26	-12.357
+LowerInnerFrontLFrThigh	LFr	3	30.39	-10.26	13.27
+LowerOuterFrontRFrThigh	RFr	3	30.39	10.544	-13.27
+LowerInnerFrontLBkThigh	LBk	3	34.173	-10.26	12.357
+LowerOuterFrontRBkThigh	RBk	3	34.173	10.544	-12.357
+LowerOuterBackLFrThigh	LFr	3	34.173	10.217	-12.357
+LowerInnerBackRFrThigh	RFr	3	34.173	-9.928	12.357
+LowerOuterBackLBkThigh	LBk	3	30.39	10.217	-13.27
+LowerInnerBackRBkThigh	RBk	3	30.39	-9.928	13.27
+LowerInnerBackLFrThigh	LFr	3	34.173	-9.928	-12.357
+LowerOuterBackRFrThigh	RFr	3	34.173	10.217	12.357
+LowerInnerBackLBkThigh	LBk	3	30.39	-9.928	-13.27
+LowerOuterBackRBkThigh	RBk	3	30.39	10.217	13.27
+UpperOuterFrontLFrThigh	LFr	3	11.262	-10.257	14.729
+UpperInnerFrontRFrThigh	RFr	3	0	11.375	-14.729
+UpperOuterFrontLBkThigh	LBk	3	11.262	-10.257	14.729
+UpperInnerFrontRBkThigh	RBk	3	0	11.375	-14.729
+UpperInnerFrontLFrThigh	LFr	3	0	11.375	14.729
+UpperOuterFrontRFrThigh	RFr	3	11.262	-10.257	-14.729
+UpperInnerFrontLBkThigh	LBk	3	0	11.375	14.729
+UpperOuterFrontRBkThigh	RBk	3	11.262	-10.257	-14.729
+UpperOuterBackLFrThigh	LFr	3	11.262	-10.257	-14.729
+UpperInnerBackRFrThigh	RFr	3	0	11.375	14.729
+UpperOuterBackLBkThigh	LBk	3	11.262	-10.257	-14.729
+UpperInnerBackRBkThigh	RBk	3	0	11.375	14.729
+UpperInnerBackLFrThigh	LFr	3	0	11.375	-14.729
+UpperOuterBackRFrThigh	RFr	3	11.262	-10.257	14.729
+UpperInnerBackLBkThigh	LBk	3	0	11.375	-14.729
+UpperOuterBackRBkThigh	RBk	3	11.262	-10.257	14.729
Index: tools/test/kinematics/IPorig/210scale.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/210scale.txt
diff -N tools/test/kinematics/IPorig/210scale.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/210scale.txt	11 Oct 2004 19:45:00 -0000	1.2
@@ -0,0 +1,7 @@
+Camera 1.21985792042
+Mouth 1.21985792042
+IR 1
+LFr 0.707741821982
+RFr 0.707741821982
+LBk 0.707741821982
+RBk 0.707741821982
Index: tools/test/kinematics/IPorig/220.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/220.txt
diff -N tools/test/kinematics/IPorig/220.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/220.txt	18 Oct 2004 23:14:13 -0000	1.4
@@ -0,0 +1,103 @@
+LFr:elvtr	LFr	2	0	0	0
+LFr:rotor	LFr	3	0	0	0
+LFr:knee~	LFr	4	0	0	0
+RFr:elvtr	RFr	2	0	0	0
+RFr:rotor	RFr	3	0	0	0
+RFr:knee~	RFr	4	0	0	0
+LBk:elvtr	LBk	2	0	0	0
+LBk:rotor	LBk	3	0	0	0
+LBk:knee~	LBk	4	0	0	0
+RBk:elvtr	RBk	2	0	0	0
+RBk:rotor	RBk	3	0	0	0
+RBk:knee~	RBk	4	0	0	0
+NECK:tilt	Camera	2	0	0	0
+NECK:pan~	Camera	3	0	0	0
+NECK:nod~	Camera	4	0	0	0
+Base	Camera	0	0	0	0
+LFrPaw	LFr	5	0	0	0
+RFrPaw	RFr	5	0	0	0
+LBkPaw	LBk	5	0	0	0
+RBkPaw	RBk	5	0	0	0
+Camera	Camera	6	0	0	0
+IR	IR	6	0	0	0
+LowerLeftSnout	Camera	4	-20.075	17.745	71.039
+LowerRightSnout	Camera	4	20.075	17.745	71.039
+UpperLeftSnout	Camera	4	-33.782	-22.574	71.039
+UpperRightSnout	Camera	4	33.782	-22.574	71.039
+LeftMicrophone	Camera	4	-52.213	-17.71	0
+RightMicrophone	Camera	4	52.213	-17.71	0
+AntennaBase	Camera	4	28.558	-44.223	-1.279
+AntennaTip	Camera	4	28.558	-82.504	-15.888
+HeadLight	Camera	4	0	-56.295	46.32
+ToeLFrPaw	LFr	5	13.068	22.315	0
+ToeRFrPaw	RFr	5	13.068	22.315	0
+ToeLBkPaw	LBk	5	-3.461	25.628	0
+ToeRBkPaw	RBk	5	-3.461	25.628	0
+LowerOuterFrontLFrShin	LFr	4	36.856	14.853	-11.213
+LowerInnerFrontRFrShin	RFr	4	36.856	14.853	-10.393
+LowerOuterFrontLBkShin	LBk	4	16.534	-21.884	11.213
+LowerInnerFrontRBkShin	RBk	4	16.534	-21.884	10.393
+LowerInnerFrontLFrShin	LFr	4	36.856	14.853	10.393
+LowerOuterFrontRFrShin	RFr	4	36.856	14.853	11.213
+LowerInnerFrontLBkShin	LBk	4	16.534	-21.884	-10.393
+LowerOuterFrontRBkShin	RBk	4	16.534	-21.884	-11.213
+LowerOuterBackLFrShin	LFr	4	32.479	-18.491	-11.213
+LowerInnerBackRFrShin	RFr	4	32.479	-18.491	-10.393
+LowerOuterBackLBkShin	LBk	4	46.709	-5.975	11.213
+LowerInnerBackRBkShin	RBk	4	46.709	-5.975	10.393
+LowerInnerBackLFrShin	LFr	4	32.479	-18.491	10.393
+LowerOuterBackRFrShin	RFr	4	32.479	-18.491	11.213
+LowerInnerBackLBkShin	LBk	4	46.709	-5.975	-10.393
+LowerOuterBackRBkShin	RBk	4	46.709	-5.975	-11.213
+MiddleOuterBackLBkShin	LBk	4	31.079	5.262	11.213
+MiddleInnerBackRBkShin	RBk	4	31.079	5.262	10.393
+MiddleInnerBackLBkShin	LBk	4	31.079	5.262	-10.393
+MiddleOuterBackRBkShin	RBk	4	31.079	5.262	-11.213
+UpperOuterFrontLFrShin	LFr	4	8.379	3.9	-11.213
+UpperInnerFrontRFrShin	RFr	4	8.379	3.9	-10.393
+UpperOuterFrontLBkShin	LBk	4	5.688	-16.035	11.213
+UpperInnerFrontRBkShin	RBk	4	5.688	-16.035	10.393
+UpperInnerFrontLFrShin	LFr	4	8.379	3.9	10.393
+UpperOuterFrontRFrShin	RFr	4	8.379	3.9	11.213
+UpperInnerFrontLBkShin	LBk	4	5.688	-16.035	-10.393
+UpperOuterFrontRBkShin	RBk	4	5.688	-16.035	-11.213
+UpperOuterBackLFrShin	LFr	4	-0.978	-16.947	-11.213
+UpperInnerBackRFrShin	RFr	4	-0.978	-16.947	-10.393
+UpperOuterBackLBkShin	LBk	4	9.658	3.472	11.213
+UpperInnerBackRBkShin	RBk	4	9.658	3.472	10.393
+UpperInnerBackLFrShin	LFr	4	-0.978	-16.947	10.393
+UpperOuterBackRFrShin	RFr	4	-0.978	-16.947	11.213
+UpperInnerBackLBkShin	LBk	4	9.658	3.472	-10.393
+UpperOuterBackRBkShin	RBk	4	9.658	3.472	-11.213
+LowerOuterFrontLFrThigh	LFr	3	26.074	10.829	12.205
+LowerInnerFrontRFrThigh	RFr	3	26.074	-10.612	-12.205
+LowerOuterFrontLBkThigh	LBk	3	30.305	10.829	12.608
+LowerInnerFrontRBkThigh	RBk	3	30.305	-10.612	-12.608
+LowerInnerFrontLFrThigh	LFr	3	26.074	-10.612	12.205
+LowerOuterFrontRFrThigh	RFr	3	26.074	10.829	-12.205
+LowerInnerFrontLBkThigh	LBk	3	30.305	-10.612	12.608
+LowerOuterFrontRBkThigh	RBk	3	30.305	10.829	-12.608
+LowerOuterBackLFrThigh	LFr	3	30.305	11.271	-12.608
+LowerInnerBackRFrThigh	RFr	3	30.305	-10.612	12.608
+LowerOuterBackLBkThigh	LBk	3	26.074	11.271	-12.205
+LowerInnerBackRBkThigh	RBk	3	26.074	-10.612	12.205
+LowerInnerBackLFrThigh	LFr	3	30.305	-10.612	-12.608
+LowerOuterBackRFrThigh	RFr	3	30.305	11.271	12.608
+LowerInnerBackLBkThigh	LBk	3	26.074	-10.612	-12.205
+LowerOuterBackRBkThigh	RBk	3	26.074	11.271	12.205
+UpperOuterFrontLFrThigh	LFr	3	10.785	10.506	11.845
+UpperInnerFrontRFrThigh	RFr	3	10.785	-10.612	-11.845
+UpperOuterFrontLBkThigh	LBk	3	10.785	10.506	11.845
+UpperInnerFrontRBkThigh	RBk	3	10.785	-10.612	-11.845
+UpperInnerFrontLFrThigh	LFr	3	10.785	-10.612	11.845
+UpperOuterFrontRFrThigh	RFr	3	10.785	10.506	-11.845
+UpperInnerFrontLBkThigh	LBk	3	10.785	-10.612	11.845
+UpperOuterFrontRBkThigh	RBk	3	10.785	10.506	-11.845
+UpperOuterBackLFrThigh	LFr	3	10.785	10.506	-11.845
+UpperInnerBackRFrThigh	RFr	3	10.785	-10.612	11.845
+UpperOuterBackLBkThigh	LBk	3	10.785	10.506	-11.845
+UpperInnerBackRBkThigh	RBk	3	10.785	-10.612	11.845
+UpperInnerBackLFrThigh	LFr	3	10.785	-10.612	-11.845
+UpperOuterBackRFrThigh	RFr	3	10.785	10.506	11.845
+UpperInnerBackLBkThigh	LBk	3	10.785	-10.612	-11.845
+UpperOuterBackRBkThigh	RBk	3	10.785	10.506	11.845
Index: tools/test/kinematics/IPorig/220scale.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/220scale.txt
diff -N tools/test/kinematics/IPorig/220scale.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/220scale.txt	11 Oct 2004 19:45:00 -0000	1.2
@@ -0,0 +1,6 @@
+Camera 1.22638841967
+IR 1
+LFr 0.707741821982
+RFr 0.707741821982
+LBk 0.707741821982
+RBk 0.707741821982
Index: tools/test/kinematics/IPorig/7.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/7.txt
diff -N tools/test/kinematics/IPorig/7.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/7.txt	18 Oct 2004 23:14:13 -0000	1.6
@@ -0,0 +1,122 @@
+LFr:elvtr	LFr	2	0	0	0
+LFr:rotor	LFr	3	0	0	0
+LFr:knee~	LFr	4	0	0	0
+RFr:elvtr	RFr	2	0	0	0
+RFr:rotor	RFr	3	0	0	0
+RFr:knee~	RFr	4	0	0	0
+LBk:elvtr	LBk	2	0	0	0
+LBk:rotor	LBk	3	0	0	0
+LBk:knee~	LBk	4	0	0	0
+RBk:elvtr	RBk	2	0	0	0
+RBk:rotor	RBk	3	0	0	0
+RBk:knee~	RBk	4	0	0	0
+NECK:tilt	Camera	2	0	0	0
+NECK:pan~	Camera	3	0	0	0
+NECK:nod~	Camera	4	0	0	0
+MOUTH~~~~	Mouth	5	0	0	0
+Base	Camera	0	0	0	0
+LFrPaw	LFr	5	0	0	0
+RFrPaw	RFr	5	0	0	0
+LBkPaw	LBk	5	0	0	0
+RBkPaw	RBk	5	0	0	0
+Camera	Camera	6	0	0	0
+NearIR	NearIR	6	0	0	0
+FarIR	FarIR	6	0	0	0
+ChestIR	ChestIR	3	0	0	0
+LowerLeftLowerLip	Mouth	5	53.667	16.127	-21.188
+LowerRightLowerLip	Mouth	5	53.667	16.127	21.188
+UpperLeftLowerLip	Mouth	5	50.419	14.718	-14.973
+UpperRightLowerLip	Mouth	5	50.419	14.718	14.973
+LowerLeftUpperLip	Mouth	4	104.465	-29.285	-14.973
+LowerRightUpperLip	Mouth	4	104.465	-29.285	14.973
+LowerLeftSnout	Camera	4	71.234	-27.781	-48.99
+LowerRightSnout	Camera	4	71.234	-27.781	48.99
+UpperLeftSnout	Camera	4	71.234	9.992	-34.53
+UpperRightSnout	Camera	4	71.234	9.992	34.53
+LeftMicrophone	Camera	4	-14.657	19.571	-61.668
+RightMicrophone	Camera	4	-14.657	19.571	61.668
+HeadButton	Camera	4	-10.121	54.115	0
+ToeLFrPaw	LFr	5	4.603	18.943	0
+ToeRFrPaw	RFr	5	4.603	18.943	0
+ToeLBkPaw	LBk	5	-4.112	17.796	0
+ToeRBkPaw	RBk	5	-4.112	17.796	0
+LowerOuterFrontLFrShin	LFr	4	38.015	13.616	-15.743
+LowerInnerFrontRFrShin	RFr	4	38.015	13.616	-9.718
+LowerOuterFrontLBkShin	LBk	4	26.395	-21.709	15.743		
+LowerInnerFrontRBkShin	RBk	4	26.395	-21.709	9.718
+LowerInnerFrontLFrShin	LFr	4	38.015	13.616	9.718
+LowerOuterFrontRFrShin	RFr	4	38.015	13.616	15.743
+LowerInnerFrontLBkShin	LBk	4	26.395	-21.709	-9.718
+LowerOuterFrontRBkShin	RBk	4	26.395	-21.709	-15.743
+LowerOuterMiddleLFrShin	LFr	4	40.395	-9.984	-15.743
+LowerInnerMiddleRFrShin	RFr	4	40.395	-9.984	-9.718
+LowerOuterMiddleLBkShin	LBk	4	48.211	-5.348	15.743
+LowerInnerMiddleRBkShin	RBk	4	48.211	-5.348	9.718
+LowerInnerMiddleLFrShin	LFr	4	40.395	-9.984	9.718
+LowerOuterMiddleRFrShin	RFr	4	40.395	-9.984	15.743
+LowerInnerMiddleLBkShin	LBk	4	48.211	-5.348	-9.718
+LowerOuterMiddleRBkShin	RBk	4	48.211	-5.348	-15.743
+LowerOuterBackLFrShin	LFr	4	26.016	-16.926	-15.743
+LowerInnerBackRFrShin	RFr	4	26.016	-16.926	-9.718
+LowerOuterBackLBkShin	LBk	4	45.602	5.249	15.743
+LowerInnerBackRBkShin	RBk	4	45.602	5.249	9.718
+LowerInnerBackLFrShin	LFr	4	26.016	-16.926	9.718
+LowerOuterBackRFrShin	RFr	4	26.016	-16.926	15.743
+LowerInnerBackLBkShin	LBk	4	45.602	5.249	-9.718
+LowerOuterBackRBkShin	RBk	4	45.602	5.249	-15.743
+MiddleOuterMiddleLFrShin	LFr	4	26.962	-6.869	-17.788
+MiddleInnerMiddleRFrShin	RFr	4	26.962	-6.869	-11.766
+MiddleOuterMiddleLBkShin	LBk	4	26.685	-7.267	17.788
+MiddleInnerMiddleRBkShin	RBk	4	26.685	-7.267	11.766
+MiddleInnerMiddleLFrShin	LFr	4	26.962	-6.869	11.766
+MiddleOuterMiddleRFrShin	RFr	4	26.962	-6.869	17.788
+MiddleInnerMiddleLBkShin	LBk	4	26.685	-7.267	-11.766
+MiddleOuterMiddleRBkShin	RBk	4	26.685	-7.267	-17.788
+UpperOuterFrontLFrShin	LFr	4	18.777	9.452	-15.018
+UpperInnerFrontRFrShin	RFr	4	18.777	9.452	-8.992
+UpperOuterFrontLBkShin	LBk	4	1.803	-14.371	15.018
+UpperInnerFrontRBkShin	RBk	4	1.803	-14.371	8.992
+UpperInnerFrontLFrShin	LFr	4	18.777	9.452	8.992
+UpperOuterFrontRFrShin	RFr	4	18.777	9.452	15.018
+UpperInnerFrontLBkShin	LBk	4	1.803	-14.371	-8.992
+UpperOuterFrontRBkShin	RBk	4	1.803	-14.371	-15.018
+UpperOuterBackLFrShin	LFr	4	4.101	-12.860	-15.018
+UpperInnerBackRFrShin	RFr	4	4.101	-12.860	-8.992
+UpperOuterBackLBkShin	LBk	4	21.072	6.169	15.018
+UpperInnerBackRBkShin	RBk	4	21.072	6.169	8.992
+UpperInnerBackLFrShin	LFr	4	4.101	-12.860	8.992
+UpperOuterBackRFrShin	RFr	4	4.101	-12.860	15.018
+UpperInnerBackLBkShin	LBk	4	21.072	6.169	-8.992
+UpperOuterBackRBkShin	RBk	4	21.072	6.169	-15.018
+LowerOuterFrontLFrThigh	LFr	3	30.738	9.321	11.02
+LowerInnerFrontRFrThigh	RFr	3	30.738	-3.233	-11.02
+LowerOuterFrontLBkThigh	LBk	3	30.738	9.321	11.02
+LowerInnerFrontRBkThigh	RBk	3	30.738	-3.233	-11.02
+LowerInnerFrontLFrThigh	LFr	3	30.738	-3.233	11.02
+LowerOuterFrontRFrThigh	RFr	3	30.738	9.321	-11.02
+LowerInnerFrontLBkThigh	LBk	3	30.738	-3.233	11.02
+LowerOuterFrontRBkThigh	RBk	3	30.738	9.321	-11.02
+LowerOuterBackLFrThigh	LFr	3	30.738	9.321	-11.02
+LowerInnerBackRFrThigh	RFr	3	30.738	-3.233	11.02
+LowerOuterBackLBkThigh	LBk	3	30.738	9.321	-11.02
+LowerInnerBackRBkThigh	RBk	3	30.738	-3.233	11.02
+LowerInnerBackLFrThigh	LFr	3	30.738	-3.233	-11.02
+LowerOuterBackRFrThigh	RFr	3	30.738	9.321	11.02
+LowerInnerBackLBkThigh	LBk	3	30.738	-3.233	-11.02
+LowerOuterBackRBkThigh	RBk	3	30.738	9.321	11.02
+UpperOuterFrontLFrThigh	LFr	3	0	6.61	11.02
+UpperInnerFrontRFrThigh	RFr	3	0	-3.233	-11.02
+UpperOuterFrontLBkThigh	LBk	3	0	6.61	11.02
+UpperInnerFrontRBkThigh	RBk	3	0	-3.233	-11.02
+UpperInnerFrontLFrThigh	LFr	3	0	-3.233	11.02
+UpperOuterFrontRFrThigh	RFr	3	0	6.61	-11.02
+UpperInnerFrontLBkThigh	LBk	3	0	-3.233	11.02
+UpperOuterFrontRBkThigh	RBk	3	0	6.61	-11.02
+UpperOuterBackLFrThigh	LFr	3	0	6.61	-11.02
+UpperInnerBackRFrThigh	RFr	3	0	-3.233	11.02
+UpperOuterBackLBkThigh	LBk	3	0	6.61	-11.02
+UpperInnerBackRBkThigh	RBk	3	0	-3.233	11.02
+UpperInnerBackLFrThigh	LFr	3	0	-3.233	-11.02
+UpperOuterBackRFrThigh	RFr	3	0	6.61	11.02
+UpperInnerBackLBkThigh	LBk	3	0	-3.233	-11.02
+UpperOuterBackRBkThigh	RBk	3	0	6.61	11.02
Index: tools/test/kinematics/IPorig/7scale.txt
===================================================================
RCS file: tools/test/kinematics/IPorig/7scale.txt
diff -N tools/test/kinematics/IPorig/7scale.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/7scale.txt	11 Oct 2004 19:32:07 -0000	1.1
@@ -0,0 +1,9 @@
+Camera 1.31371889651
+Mouth 1.31371889651
+NearIR 1
+FarIR 1
+ChestIR 1
+LFr 0.641075763943
+RFr 0.641075763943
+LBk 0.641075763943
+RBk 0.641075763943
Index: tools/test/kinematics/IPorig/ipenlist
===================================================================
RCS file: tools/test/kinematics/IPorig/ipenlist
diff -N tools/test/kinematics/IPorig/ipenlist
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/ipenlist	11 Oct 2004 19:32:07 -0000	1.2
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+if [ $# -lt 2 -o "$1" = "-h" -o "$1" = "--help" ] ; then
+	echo "Usage: $0 ip-file scale-file";
+	echo "  file format should be tab deliminated:"
+	echo "    first column is name,"
+	echo "    second column is the name of the chain the interest point is in,"
+	echo "    third column is the link number the interest point is relative to,"
+	echo "    fourth column is x value,"
+	echo "    fifth column is y,"
+	echo "    sixth column is z."
+	exit 2;
+fi
+
+if [ ! -r "$1" ] ; then
+	echo "Could not read file '$1'";
+	exit 1;
+fi
+
+if [ ! -r "$2" ] ; then
+	echo "Could not read file '$2'";
+	exit 1;
+fi
+
+lines=`cat "$1" | wc -l`;
+echo "[InterestPoints]";
+echo "Length: $lines";
+echo "";
+
+exec 6< "$1"
+line=1;
+
+for ((line=1;lines-line+1;line++)) ; do
+	read -u 6 -d "	" name;
+	read -u 6 -d "	" chain;
+	read -u 6 -d "	" link;
+	read -u 6 -d "	" x;
+	read -u 6 -d "	" y;
+	read -u 6 z;
+	scale=`grep $chain "$2" | sed "s/^[^0-9.]*//"`
+	x=`echo "scale=3; $x / $scale" | bc`
+	y=`echo "scale=3; $y / $scale" | bc`
+	z=`echo "scale=3; $z / $scale" | bc`
+	echo "[InterestPoint$line]";
+	echo "   name: $name";
+	echo "  chain: $chain";
+	echo "   link: $link";
+	echo "      x: $x";
+	echo "      y: $y";
+	echo "      z: $z";
+done
+
+exec 6<&-
\ No newline at end of file
Index: tools/test/kinematics/IPorig/ipsplit
===================================================================
RCS file: tools/test/kinematics/IPorig/ipsplit
diff -N tools/test/kinematics/IPorig/ipsplit
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tools/test/kinematics/IPorig/ipsplit	20 Sep 2004 21:54:40 -0000	1.1
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ $# -lt 1 -o "$1" = "-h" -o "$1" = "--help" ] ; then
+	echo "Usage: $0 ipfile [prefix]"
+	exit 2;
+fi;
+
+for x in `cut -f 2 "$1" | sort | uniq` ; do
+	cut -f 2- "$1" | grep "$x" | cut -f 2- > "$2$x.txt"
+done
